Data Exploration and Wrangling
The first step in performing a machine learning analysis is to explore the data to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe which can be used to define the input for later sequential steps. This will make more sense when we have multiple sequential steps using the same data object. To use the pipe notation we need to install and load dplyr as well.
For example here we will first grab the pm data object, then we use the glimpse() function on it based on the pipe notation.
Observations: 876
Variables: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.1…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6…
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, …
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.287…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85…
$ state <chr> "Alabama", "Alabama", "Alabama", "Al…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKal…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoal…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.5347…
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 3…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 3021…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038,…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, …
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430,…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.7214…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.5171…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409…
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173…
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.909…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.3101…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.5858…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.508…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.559…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.57312730…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.58191745…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.8876…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, …
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, …
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.1719…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 4…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 1…
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, …
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, …
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, …
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, …
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, …
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.083…
We can see that there are 876 monitors and that we have 50 total variables - one of which is the outcome. In this case our outcome variable is called value.
Notice that some of the variables that we would think of as factors (categorical) are currently of class double as indicated by the <dbl> just to the right of the column names/variable names in the glimpse() output. For example the monitor ID (id), the Federal Information Processing Standard number for the county where the monitor was located (fips), as well as the zcta
Let’s convert these variables into factors. We can do this using the mutate_at() function of the dplyr package and the as.factor() base function.
In this case we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input but also reassign the output to the same data object name.
Observations: 876
Variables: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6…
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, …
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.287…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85…
$ state <chr> "Alabama", "Alabama", "Alabama", "Al…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKal…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoal…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.5347…
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 3…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 3021…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038,…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, …
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430,…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.7214…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.5171…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409…
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173…
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.909…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.3101…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.5858…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.508…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.559…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.57312730…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.58191745…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.8876…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, …
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, …
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.1719…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 4…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 1…
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, …
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, …
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, …
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, …
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, …
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.083…
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
The skim() function of the skimr package is also really helpful for getting a general sense of your data.
Data summary
| Name |
pm |
| Number of rows |
876 |
| Number of columns |
50 |
| _______________________ |
|
| Column type frequency: |
|
| character |
3 |
| factor |
3 |
| numeric |
44 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| state |
0 |
1 |
4 |
20 |
0 |
49 |
0 |
| county |
0 |
1 |
3 |
20 |
0 |
471 |
0 |
| city |
0 |
1 |
4 |
48 |
0 |
607 |
0 |
Variable type: factor
| id |
0 |
1 |
FALSE |
876 |
100: 1, 102: 1, 103: 1, 104: 1 |
| fips |
0 |
1 |
FALSE |
569 |
170: 12, 603: 10, 261: 9, 107: 8 |
| zcta |
0 |
1 |
FALSE |
842 |
475: 3, 110: 2, 160: 2, 290: 2 |
Variable type: numeric
| value |
0 |
1 |
10.81 |
2.580000e+00 |
3.02 |
9.27 |
11.15 |
12.37 |
2.316000e+01 |
▂▆▇▁▁ |
| lat |
0 |
1 |
38.48 |
4.620000e+00 |
25.47 |
35.03 |
39.30 |
41.66 |
4.840000e+01 |
▁▃▅▇▂ |
| lon |
0 |
1 |
-91.74 |
1.496000e+01 |
-124.18 |
-99.16 |
-87.47 |
-80.69 |
-6.804000e+01 |
▃▂▃▇▃ |
| CMAQ |
0 |
1 |
8.41 |
2.970000e+00 |
1.63 |
6.53 |
8.62 |
10.24 |
2.313000e+01 |
▃▇▃▁▁ |
| zcta_area |
0 |
1 |
183173481.91 |
5.425989e+08 |
15459.00 |
14204601.75 |
37653560.50 |
160041508.25 |
8.164821e+09 |
▇▁▁▁▁ |
| zcta_pop |
0 |
1 |
24227.58 |
1.777216e+04 |
0.00 |
9797.00 |
22014.00 |
35004.75 |
9.539700e+04 |
▇▇▃▁▁ |
| imp_a500 |
0 |
1 |
24.72 |
1.934000e+01 |
0.00 |
3.70 |
25.12 |
40.22 |
6.961000e+01 |
▇▅▆▃▂ |
| imp_a1000 |
0 |
1 |
24.26 |
1.802000e+01 |
0.00 |
5.32 |
24.53 |
38.59 |
6.750000e+01 |
▇▅▆▃▁ |
| imp_a5000 |
0 |
1 |
19.93 |
1.472000e+01 |
0.05 |
6.79 |
19.07 |
30.11 |
7.460000e+01 |
▇▆▃▁▁ |
| imp_a10000 |
0 |
1 |
15.82 |
1.381000e+01 |
0.09 |
4.54 |
12.36 |
24.17 |
7.209000e+01 |
▇▃▂▁▁ |
| imp_a15000 |
0 |
1 |
13.43 |
1.312000e+01 |
0.11 |
3.24 |
9.67 |
20.55 |
7.110000e+01 |
▇▃▁▁▁ |
| county_area |
0 |
1 |
3768701992.12 |
6.212830e+09 |
33703512.00 |
1116536297.50 |
1690826566.50 |
2878192209.00 |
5.194723e+10 |
▇▁▁▁▁ |
| county_pop |
0 |
1 |
687298.44 |
1.293489e+06 |
783.00 |
100948.00 |
280730.50 |
743159.00 |
9.818605e+06 |
▇▁▁▁▁ |
| log_dist_to_prisec |
0 |
1 |
6.19 |
1.410000e+00 |
-1.46 |
5.43 |
6.36 |
7.15 |
1.045000e+01 |
▁▁▃▇▁ |
| log_pri_length_5000 |
0 |
1 |
9.82 |
1.080000e+00 |
8.52 |
8.52 |
10.05 |
10.73 |
1.205000e+01 |
▇▂▆▅▂ |
| log_pri_length_10000 |
0 |
1 |
10.92 |
1.130000e+00 |
9.21 |
9.80 |
11.17 |
11.83 |
1.302000e+01 |
▇▂▇▇▃ |
| log_pri_length_15000 |
0 |
1 |
11.50 |
1.150000e+00 |
9.62 |
10.87 |
11.72 |
12.40 |
1.359000e+01 |
▆▂▇▇▃ |
| log_pri_length_25000 |
0 |
1 |
12.24 |
1.100000e+00 |
10.13 |
11.69 |
12.46 |
13.05 |
1.436000e+01 |
▅▃▇▇▃ |
| log_prisec_length_500 |
0 |
1 |
6.99 |
9.500000e-01 |
6.21 |
6.21 |
6.21 |
7.82 |
9.400000e+00 |
▇▁▂▂▁ |
| log_prisec_length_1000 |
0 |
1 |
8.56 |
7.900000e-01 |
7.60 |
7.60 |
8.66 |
9.20 |
1.047000e+01 |
▇▅▆▃▁ |
| log_prisec_length_5000 |
0 |
1 |
11.28 |
7.800000e-01 |
8.52 |
10.91 |
11.42 |
11.83 |
1.278000e+01 |
▁▁▃▇▃ |
| log_prisec_length_10000 |
0 |
1 |
12.41 |
7.300000e-01 |
9.21 |
11.99 |
12.53 |
12.94 |
1.385000e+01 |
▁▁▃▇▅ |
| log_prisec_length_15000 |
0 |
1 |
13.03 |
7.200000e-01 |
9.62 |
12.59 |
13.13 |
13.57 |
1.441000e+01 |
▁▁▃▇▅ |
| log_prisec_length_25000 |
0 |
1 |
13.82 |
7.000000e-01 |
10.13 |
13.38 |
13.92 |
14.35 |
1.523000e+01 |
▁▁▃▇▆ |
| log_nei_2008_pm25_sum_10000 |
0 |
1 |
3.97 |
2.350000e+00 |
0.00 |
2.15 |
4.29 |
5.69 |
9.120000e+00 |
▆▅▇▆▂ |
| log_nei_2008_pm25_sum_15000 |
0 |
1 |
4.72 |
2.250000e+00 |
0.00 |
3.47 |
5.00 |
6.35 |
9.420000e+00 |
▃▃▇▇▂ |
| log_nei_2008_pm25_sum_25000 |
0 |
1 |
5.67 |
2.110000e+00 |
0.00 |
4.66 |
5.91 |
7.28 |
9.650000e+00 |
▂▂▇▇▃ |
| log_nei_2008_pm10_sum_10000 |
0 |
1 |
4.35 |
2.320000e+00 |
0.00 |
2.69 |
4.62 |
6.07 |
9.340000e+00 |
▅▅▇▇▂ |
| log_nei_2008_pm10_sum_15000 |
0 |
1 |
5.10 |
2.180000e+00 |
0.00 |
3.87 |
5.39 |
6.72 |
9.710000e+00 |
▂▃▇▇▂ |
| log_nei_2008_pm10_sum_25000 |
0 |
1 |
6.07 |
2.010000e+00 |
0.00 |
5.10 |
6.37 |
7.52 |
9.880000e+00 |
▁▂▆▇▃ |
| popdens_county |
0 |
1 |
551.76 |
1.711510e+03 |
0.26 |
40.77 |
156.67 |
510.81 |
2.682191e+04 |
▇▁▁▁▁ |
| popdens_zcta |
0 |
1 |
1279.66 |
2.757490e+03 |
0.00 |
101.15 |
610.35 |
1382.52 |
3.041884e+04 |
▇▁▁▁▁ |
| nohs |
0 |
1 |
6.99 |
7.210000e+00 |
0.00 |
2.70 |
5.10 |
8.80 |
1.000000e+02 |
▇▁▁▁▁ |
| somehs |
0 |
1 |
10.17 |
6.200000e+00 |
0.00 |
5.90 |
9.40 |
13.90 |
7.220000e+01 |
▇▂▁▁▁ |
| hs |
0 |
1 |
30.32 |
1.140000e+01 |
0.00 |
23.80 |
30.75 |
36.10 |
1.000000e+02 |
▂▇▂▁▁ |
| somecollege |
0 |
1 |
21.58 |
8.600000e+00 |
0.00 |
17.50 |
21.30 |
24.70 |
1.000000e+02 |
▆▇▁▁▁ |
| associate |
0 |
1 |
7.13 |
4.010000e+00 |
0.00 |
4.90 |
7.10 |
8.80 |
7.140000e+01 |
▇▁▁▁▁ |
| bachelor |
0 |
1 |
14.90 |
9.710000e+00 |
0.00 |
8.80 |
12.95 |
19.22 |
1.000000e+02 |
▇▂▁▁▁ |
| grad |
0 |
1 |
8.91 |
8.650000e+00 |
0.00 |
3.90 |
6.70 |
11.00 |
1.000000e+02 |
▇▁▁▁▁ |
| pov |
0 |
1 |
14.95 |
1.133000e+01 |
0.00 |
6.50 |
12.10 |
21.22 |
6.590000e+01 |
▇▅▂▁▁ |
| hs_orless |
0 |
1 |
47.48 |
1.675000e+01 |
0.00 |
37.92 |
48.65 |
59.10 |
1.000000e+02 |
▁▃▇▃▁ |
| urc2013 |
0 |
1 |
2.92 |
1.520000e+00 |
1.00 |
2.00 |
3.00 |
4.00 |
6.000000e+00 |
▇▅▃▂▁ |
| urc2006 |
0 |
1 |
2.97 |
1.520000e+00 |
1.00 |
2.00 |
3.00 |
4.00 |
6.000000e+00 |
▇▅▃▂▁ |
| aod |
0 |
1 |
43.70 |
1.956000e+01 |
5.00 |
31.66 |
40.17 |
49.67 |
1.430000e+02 |
▃▇▁▁▁ |
Notice how there is a column called n_missing about the number of values that are missing. It looks like our data is very complete and we do not have any missing data. This is also indicated by the complete_rate variable, which shows the ratio of completeness, in our case all variables have a value of 1 indicating they are fully complete.
The n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data, and we know that the data should be of the contiguous states. Let’s take a look to see which states are included:
Looks like “District of Columbia” is being included as a state. We can see that indeed Alaska and Hawaii are not included in the data.
Here is another method of looking at the data using the dfSummary() function of the summarytoolspackage. We need to copy and paste the output into the rmarkdown.
Dimensions: 876 x 50
Duplicates: 0
| 1 |
id
[factor] |
1. 1003.001
2. 1027.0001
3. 1033.1002
4. 1049.1003
5. 1055.001
6. 1069.0003
7. 1073.0023
8. 1073.1005
9. 1073.1009
10. 1073.101
[ 866 others ] |
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
866 (98.9%) |
 |
876
(100%) |
0
(0%) |
| 2 |
value
[numeric] |
Mean (sd) : 10.8 (2.6)
min < med < max:
3 < 11.2 < 23.2
IQR (CV) : 3.1 (0.2) |
875 distinct values |
 |
876
(100%) |
0
(0%) |
| 3 |
fips
[factor] |
1. 1003
2. 1027
3. 1033
4. 1049
5. 1055
6. 1069
7. 1073
8. 1089
9. 1097
10. 1101
[ 559 others ] |
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
8 ( 0.9%)
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
858 (98.0%) |
 |
876
(100%) |
0
(0%) |
| 4 |
lat
[numeric] |
Mean (sd) : 38.5 (4.6)
min < med < max:
25.5 < 39.3 < 48.4
IQR (CV) : 6.6 (0.1) |
876 distinct values |
 |
876
(100%) |
0
(0%) |
| 5 |
lon
[numeric] |
Mean (sd) : -91.7 (15)
min < med < max:
-124.2 < -87.5 < -68
IQR (CV) : 18.5 (-0.2) |
876 distinct values |
 |
876
(100%) |
0
(0%) |
| 6 |
state
[character] |
1. California
2. Ohio
3. Illinois
4. Indiana
5. North Carolina
6. Pennsylvania
7. Michigan
8. Florida
9. Georgia
10. Texas
[ 39 others ] |
85 ( 9.7%)
44 ( 5.0%)
38 ( 4.3%)
36 ( 4.1%)
35 ( 4.0%)
32 ( 3.7%)
30 ( 3.4%)
29 ( 3.3%)
28 ( 3.2%)
27 ( 3.1%)
492 (56.2%) |
 |
876
(100%) |
0
(0%) |
| 7 |
county
[character] |
1. Jefferson
2. Cook
3. Hamilton
4. Lake
5. Los Angeles
6. Wayne
7. Washington
8. Cuyahoga
9. Jackson
10. Madison
[ 461 others ] |
18 ( 2.1%)
12 ( 1.4%)
11 ( 1.3%)
11 ( 1.3%)
10 ( 1.1%)
10 ( 1.1%)
9 ( 1.0%)
7 ( 0.8%)
7 ( 0.8%)
7 ( 0.8%)
774 (88.4%) |
 |
876
(100%) |
0
(0%) |
| 8 |
city
[character] |
1. Not in a city
2. New York
3. Cleveland
4. Baltimore
5. Chicago
6. Detroit
7. Milwaukee
8. New Haven
9. Philadelphia
10. Springfield
[ 597 others ] |
103 (11.8%)
9 ( 1.0%)
6 ( 0.7%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
5 ( 0.6%)
723 (82.5%) |
 |
876
(100%) |
0
(0%) |
| 9 |
CMAQ | Me [numeric] |
an (sd) : 8.4 (3) | 60 min < med < max:
1.6 < 8.6 < 23.1
IQR (CV) : 3.7 (0.4) |
1 distinct values |  | 87 |
6 | 0
(100%) |
(0%) |
| 10 |
zcta
[factor] |
1. 1022
2. 1103
3. 1201
4. 1608
5. 1832
6. 1840
7. 1863
8. 1904
9. 2113
10. 2119
[ 832 others ] |
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
2 ( 0.2%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
1 ( 0.1%)
864 (98.6%) |
 |
876
(100%) |
0
(0%) |
| 11 |
zcta_area
[numeric] |
Mean (sd) : 183173481.9 (542598878.5)
min < med < max:
15459 < 37653560.5 < 8164820625
IQR (CV) : 145836906.5 (3) |
842 distinct values |
 |
876
(100%) |
0
(0%) |
| 12 |
zcta_pop
[numeric] |
Mean (sd) : 24227.6 (17772.2)
min < med < max:
0 < 22014 < 95397
IQR (CV) : 25207.8 (0.7) |
837 distinct values |
 |
876
(100%) |
0
(0%) |
| 13 |
imp_a500
[numeric] |
Mean (sd) : 24.7 (19.3)
min < med < max:
0 < 25.1 < 69.6
IQR (CV) : 36.5 (0.8) |
816 distinct values |
 |
876
(100%) |
0
(0%) |
| 14 |
imp_a1000
[numeric] |
Mean (sd) : 24.3 (18)
min < med < max:
0 < 24.5 < 67.5
IQR (CV) : 33.3 (0.7) |
860 distinct values |
 |
876
(100%) |
0
(0%) |
| 15 |
imp_a5000
[numeric] |
Mean (sd) : 19.9 (14.7)
min < med < max:
0.1 < 19.1 < 74.6
IQR (CV) : 23.3 (0.7) |
870 distinct values |
 |
876
(100%) |
0
(0%) |
| 16 |
imp_a10000
[numeric] |
Mean (sd) : 15.8 (13.8)
min < med < max:
0.1 < 12.4 < 72.1
IQR (CV) : 19.6 (0.9) |
870 distinct values |
 |
876
(100%) |
0
(0%) |
| 17 |
imp_a15000
[numeric] |
Mean (sd) : 13.4 (13.1)
min < med < max:
0.1 < 9.7 < 71.1
IQR (CV) : 17.3 (1) |
870 distinct values |
 |
876
(100%) |
0
(0%) |
| 18 |
county_area
[numeric] |
Mean (sd) : 3768701992.1 (6212829553.6)
min < med < max:
33703512 < 1690826566.5 < 51947229509
IQR (CV) : 1761655911.5 (1.6) |
564 distinct values |
 |
876
(100%) |
0
(0%) |
| 19 |
county_pop
[numeric] |
Mean (sd) : 687298.4 (1293488.7)
min < med < max:
783 < 280730.5 < 9818605
IQR (CV) : 642211 (1.9) |
564 distinct values |
 |
876
(100%) |
0
(0%) |
| 20 |
log_dist_to_prisec
[numeric] |
Mean (sd) : 6.2 (1.4)
min < med < max:
-1.5 < 6.4 < 10.5
IQR (CV) : 1.7 (0.2) |
870 distinct values |
 |
876
(100%) |
0
(0%) |
| 21 |
log_pri_length_5000
[numeric] |
Mean (sd) : 9.8 (1.1)
min < med < max:
8.5 < 10.1 < 12
IQR (CV) : 2.2 (0.1) |
586 distinct values |
 |
876
(100%) |
0
(0%) |
| 22 |
log_pri_length_10000
[numeric] |
Mean (sd) : 10.9 (1.1)
min < med < max:
9.2 < 11.2 < 13
IQR (CV) : 2 (0.1) |
687 distinct values |
 |
876
(100%) |
0
(0%) |
| 23 |
log_pri_length_15000
[numeric] |
Mean (sd) : 11.5 (1.1)
min < med < max:
9.6 < 11.7 < 13.6
IQR (CV) : 1.5 (0.1) |
726 distinct values |
 |
876
(100%) |
0
(0%) |
| 24 |
log_pri_length_25000
[numeric] |
Mean (sd) : 12.2 (1.1)
min < med < max:
10.1 < 12.5 < 14.4
IQR (CV) : 1.4 (0.1) |
787 distinct values |
 |
876
(100%) |
0
(0%) |
| 25 |
log_prisec_length_500
[numeric] |
Mean (sd) : 7 (1)
min < med < max:
6.2 < 6.2 < 9.4
IQR (CV) : 1.6 (0.1) |
382 distinct values |
 |
876
(100%) |
0
(0%) |
| 26 |
log_prisec_length_1000
[numeric] |
Mean (sd) : 8.6 (0.8)
min < med < max:
7.6 < 8.7 < 10.5
IQR (CV) : 1.6 (0.1) |
591 distinct values |
 |
876
(100%) |
0
(0%) |
| 27 |
log_prisec_length_5000
[numeric] |
Mean (sd) : 11.3 (0.8)
min < med < max:
8.5 < 11.4 < 12.8
IQR (CV) : 0.9 (0.1) |
852 distinct values |
 |
876
(100%) |
0
(0%) |
| 28 |
log_prisec_length_10000
[numeric] |
Mean (sd) : 12.4 (0.7)
min < med < max:
9.2 < 12.5 < 13.8
IQR (CV) : 1 (0.1) |
867 distinct values |
 |
876
(100%) |
0
(0%) |
| 29 |
log_prisec_length_15000
[numeric] |
Mean (sd) : 13 (0.7)
min < med < max:
9.6 < 13.1 < 14.4
IQR (CV) : 1 (0.1) |
869 distinct values |
 |
876
(100%) |
0
(0%) |
| 30 |
log_prisec_length_25000
[numeric] |
Mean (sd) : 13.8 (0.7)
min < med < max:
10.1 < 13.9 < 15.2
IQR (CV) : 1 (0.1) |
870 distinct values |
 |
876
(100%) |
0
(0%) |
| 31 |
log_nei_2008_pm25_sum_10000
[numeric] |
Mean (sd) : 4 (2.4)
min < med < max:
0 < 4.3 < 9.1
IQR (CV) : 3.5 (0.6) |
828 distinct values |
 |
876
(100%) |
0
(0%) |
| 32 |
log_nei_2008_pm25_sum_15000
[numeric] |
Mean (sd) : 4.7 (2.2)
min < med < max:
0 < 5 < 9.4
IQR (CV) : 2.9 (0.5) |
855 distinct values |
 |
876
(100%) |
0
(0%) |
| 33 |
log_nei_2008_pm25_sum_25000
[numeric] |
Mean (sd) : 5.7 (2.1)
min < med < max:
0 < 5.9 < 9.7
IQR (CV) : 2.6 (0.4) |
860 distinct values |
 |
876
(100%) |
0
(0%) |
| 34 |
log_nei_2008_pm10_sum_10000
[numeric] |
Mean (sd) : 4.3 (2.3)
min < med < max:
0 < 4.6 < 9.3
IQR (CV) : 3.4 (0.5) |
829 distinct values |
 |
876
(100%) |
0
(0%) |
| 35 |
log_nei_2008_pm10_sum_15000
[numeric] |
Mean (sd) : 5.1 (2.2)
min < med < max:
0 < 5.4 < 9.7
IQR (CV) : 2.8 (0.4) |
855 distinct values |
 |
876
(100%) |
0
(0%) |
| 36 |
log_nei_2008_pm10_sum_25000
[numeric] |
Mean (sd) : 6.1 (2)
min < med < max:
0 < 6.4 < 9.9
IQR (CV) : 2.4 (0.3) |
860 distinct values |
 |
876
(100%) |
0
(0%) |
| 37 |
popdens_county
[numeric] |
Mean (sd) : 551.8 (1711.5)
min < med < max:
0.3 < 156.7 < 26821.9
IQR (CV) : 470 (3.1) |
564 distinct values |
 |
876
(100%) |
0
(0%) |
| 38 |
popdens_zcta
[numeric] |
Mean (sd) : 1279.7 (2757.5)
min < med < max:
0 < 610.3 < 30418.8
IQR (CV) : 1281.4 (2.2) |
840 distinct values |
 |
876
(100%) |
0
(0%) |
| 39 |
nohs
[numeric] |
Mean (sd) : 7 (7.2)
min < med < max:
0 < 5.1 < 100
IQR (CV) : 6.1 (1) |
215 distinct values |
 |
876
(100%) |
0
(0%) |
| 40 |
somehs
[numeric] |
Mean (sd) : 10.2 (6.2)
min < med < max:
0 < 9.4 < 72.2
IQR (CV) : 8 (0.6) |
230 distinct values |
 |
876
(100%) |
0
(0%) |
| 41 |
hs
[numeric] |
Mean (sd) : 30.3 (11.4)
min < med < max:
0 < 30.8 < 100
IQR (CV) : 12.3 (0.4) |
347 distinct values |
 |
876
(100%) |
0
(0%) |
| 42 |
somecollege
[numeric] |
Mean (sd) : 21.6 (8.6)
min < med < max:
0 < 21.3 < 100
IQR (CV) : 7.2 (0.4) |
240 distinct values |
 |
876
(100%) |
0
(0%) |
| 43 |
associate
[numeric] |
Mean (sd) : 7.1 (4)
min < med < max:
0 < 7.1 < 71.4
IQR (CV) : 3.9 (0.6) |
157 distinct values |
 |
876
(100%) |
0
(0%) |
| 44 |
bachelor
[numeric] |
Mean (sd) : 14.9 (9.7)
min < med < max:
0 < 12.9 < 100
IQR (CV) : 10.4 (0.7) |
301 distinct values |
 |
876
(100%) |
0
(0%) |
| 45 |
grad
[numeric] |
Mean (sd) : 8.9 (8.6)
min < med < max:
0 < 6.7 < 100
IQR (CV) : 7.1 (1) |
245 distinct values |
 |
876
(100%) |
0
(0%) |
| 46 |
pov
[numeric] |
Mean (sd) : 15 (11.3)
min < med < max:
0 < 12.1 < 65.9
IQR (CV) : 14.7 (0.8) |
345 distinct values |
 |
876
(100%) |
0
(0%) |
| 47 |
hs_orless
[numeric] |
Mean (sd) : 47.5 (16.8)
min < med < max:
0 < 48.7 < 100
IQR (CV) : 21.2 (0.4) |
464 distinct values |
 |
876
(100%) |
0
(0%) |
| 48 |
urc2013
[numeric] |
Mean (sd) : 2.9 (1.5)
min < med < max:
1 < 3 < 6
IQR (CV) : 2 (0.5) |
1 : 203 (23.2%)
2 : 163 (18.6%)
3 : 228 (26.0%)
4 : 123 (14.0%)
5 : 101 (11.5%)
6 : 58 ( 6.6%) |
 |
876
(100%) |
0
(0%) |
| 49 |
urc2006
[numeric] |
Mean (sd) : 3 (1.5)
min < med < max:
1 < 3 < 6
IQR (CV) : 2 (0.5) |
1 : 195 (22.3%)
2 : 162 (18.5%)
3 : 221 (25.2%)
4 : 127 (14.5%)
5 : 115 (13.1%)
6 : 56 ( 6.4%) |
 |
876
(100%) |
0
(0%) |
| 50 |
aod
[numeric] |
Mean (sd) : 43.7 (19.6)
min < med < max:
5 < 40.2 < 143
IQR (CV) : 18 (0.4) |
581 distinct values |
 |
876
(100%) |
0
(0%) |
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value. This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables. We can also see that the range of some of the variables is very large, in particular the area and population related variables.
In prediction analyses, it is also useful to evaluate if any of the variables are correlated.
Intuitively we can expect some of our variables to be correlated.
We expect the development variables (imp) to be correlated with each other, we expect the road density variables to be correlated with each other, we expect the emission variables to be correlated with each other, and we also expect these variables to be correlated with one another and likely correlated with population density. We can get a nice visualization of correlation using the ggcorr() function and the ggpairs() function of the GGally package. to select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables.


Indeed, we can see that imp_a1000 and imp_a500 are perfectly correlated, as well as imp_a10000, imp_a15000.
Now let’s take a look at the road density data:


We can see that while some of the road density variables are highly correlated with one another (or anti-correlated), there arr some variables that are less correlated with one another.
Finally let’s look at the emission variables.


We would also expect the population density data might correlate with some of these variables. Let’s take a look.


Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
We seem to have some pretty extreme population values though, so let’s see what happens when we take the log value.


Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Data Analysis
Now that we have a sense of what our data is like we can get started with data analysis.
The tidymodels ecosystem
To perform our analysis we will be using the tidymodels suite of packages. You may be familiar with the older packages caret or mlr which are also for machine learning and modeling but are not a part of the tidyverse. Max Kuhn describes tidymodels like this:
“Other packages, such as caret and mlr, help to solve the R model API issue. These packages do a lot of other things too: preprocessing, model tuning, resampling, feature selection, ensembling, and so on. In the tidyverse, we strive to make our packages modular and parsnip is designed only to solve the interface issue. It is not designed to be a drop-in replacement for caret. The tidymodels package collection, which includes parsnip, has other packages for many of these tasks, and they are designed to work together. We are working towards higher-level APIs that can replicate and extend what the current model packages can do.”
The major benefits of tidymodels
- standardized workflow/format/notation across different types of algorithms
- can easily modify preprocessing, algorithm choice, and hyper-parameter tuning making optimization easy
The machine learning process
The tidymodels ecosystem - an overview
There are many packages in the tidymodels ecosystem which assist with the various steps of the machine learning process:

This is the overall process:

There are two distinct goals of supervised machine learning:
- Prediction
- Classification
We will be performing a prediction analysis (which is also refered to as regression), which aims to predict continuous outcome variables given a number of predictors/explanatory variables/features/parameters, as we have already described.
Classification on the other hand aims to discern or predict group identity for a categorical outcome based on a number of predictors/explanatory variables/features/parameters.
The overall process is the same in either case.
Splitting the Data
The first step after data exploration in machine learning analysis is to split the data into training and testing datasets.
The training dataset will be used to build and tune our model. This is the data that the model “learns” on.
The testing set will be used to evaluate the performance of our model in a more generalizable way. What do we mean by “generalizable”?
Remember that our main goal is to use our model to be able to predict air pollution levels in areas where there are no gravimetric monitors. Therefore, if our model is super good at predicting air pollution with the data that we use to build it, it might not do the best job for the areas where there are few to no monitors. This would cause us to have really good prediction accuracy and we might assume that we were going to do a good job estimating air pollution any time we use our model, but in fact this would likely not be the case. This situation is what we call overfitting .
Overfitting happens when we end up modeling not only the major relationships in our data but also the noise within our data.

If we get fairly good prediction with our testing set then we will know that our model can be applied to other data and will perform fairly well. We will discuss this more later.
We will not touch the testing set until we have completed optimizing our model with the training set. This will allow us to have a less biased evaluation of how well our model can do with other data besides the data used in the training set to build the model. Ideally you would also want a completely independent dataset to further test the performance of your model.
Here is a great description of the differences between testing and training datasets.
We will use the rsample package to perform this step.
Theinitial_split() function allows us to specify how we want to split our data. Typically data is split into 3/4 for training and 1/4 for testing.This is the default proportion and does not need to be specified. However you can change the proportion using the prop argument, which we will do that here for illustrative purposes. You can also specify a variable to stratify by with the strata argument. This is useful if you have imbalanced categorical variables and you would like to intentionally make sure that there are similar number of samples of the rarer categories in both the testing and training sets. Otherwise the split is performed randomly.
The strata argument causes the random sampling to be conducted within the stratification variable. The can help ensure that the number of data points in the training data is equivalent to the proportions in the original data set.
In the case with our dataset, perhaps we would like our training set to have similar proportions of monitors from each of the states as in the initial data. This might be useful if we want our model to be generalizable across all of the states.
We can see that indeed there are different proportions of monitors in each state by using the count() function of the dpyr package.
If our dataset were large enough it might be nice then to stratify by state, but our data is unfortunately not large enough. We will show how one would do this though for illustrative purposes. This option is often more important for classification applications of machine learning than it is for prediction.
Since the split is performed randomly, it is a good idea to use the set.seed() base function to ensure that if your rerun your code that your split will be the same next time. We can see the number of monitors in our training, testing, and original data by typing in the name of our split object. The result will look like this: <training data sample number, testing data sample number, original sample number>
<584/292/876>
Importantly the initial_split function only determines what rows of our pm data frame should be assigned for training or testing, it does not actually split the data.
To extract the testing and training data we can use the training() and testing() functions also of the rsample package.
Variable Role Assignment and Preprocessing
In tidymodels we will create a recipe, which is a standardized format for a sequence of steps for processing the data.
This can be very useful because it makes testing out different pre-processing steps or different algorithms with the same pre-processing very easy and reproducible.
Creating a recipe specifies how a dataframe of predictors should be created - it specifies what variables to be used and the preprocessing steps but it does not execute these steps or create the dataframe of predictors.
List the ingredients / specify the variables with the recipe() function
The first thing to do to create a recipe is to specify which variables we will be using as our outcome and predictors using the recipe() function. In terms of the metaphor of baking, we can think of this as listing our ingredients. The naming convention for recipe object names is *_rec or rec.

In our case recall that our value variable, which is the average annual gravimetric monitor PM2.5 concentration in ug/m3. Our predictors are all the other variables except the monitor ID, which is an id variable.
The reason not to include this variable is because this variable includes the county number and a number designating which particular monitor the values came from of the monitors there are in that county. Since this number is arbitrary and the county information is also given in the data, and the fact that each monitor only has one value in the value variable, nothing is gained by including this variable and it may instead introduce noise. However, it is useful to keep this data to take a look at what is happening later. We will show you what to do in this case in just a bit.
The simplest recipe with no preprocessing steps, would be to simply list the outcome and predictor variables.
We can do so in two ways:
- Using formula notation
- Assigning roles to each variable
Let’s look at the first way using formula notation, which looks like this:
outcome(s) ~ predictor(s)
If in the case of multiple predictors or a multivariate situation with two outcomes, use a plus sign
outcome1 + outcome2 ~ predictor1 + predictor2
If we want to include all predictors we can use a period like so:
outcome_variable_name ~ .
Now with our data we will start by making a recipe for our training data. In the simplest case we might use all predictors like this:
Data Recipe
Inputs:
role #variables
outcome 1
predictor 49
However, to deal with the id variable we could use the update_role() function of the recipes package:
Data Recipe
Inputs:
role #variables
id variable 1
outcome 1
predictor 48
We could also specify the outcome and predictors in the same way as the id variable. Please see here for examples of other roles for variables. The role can be actually be any value.
The order is important here, as we first make all variables predictors and then override this role for the outcome and id variable. We will use the everything() function of the dplyr package to start with all of the variables in train_pm.
Data Recipe
Inputs:
role #variables
id variable 1
outcome 1
predictor 48
If we want to take a look at our formula from our recipe we can do use the formula() function of the stats package.
value ~ fips + lat + lon + state + county + city + CMAQ + zcta +
zcta_area + zcta_pop + imp_a500 + imp_a1000 + imp_a5000 +
imp_a10000 + imp_a15000 + county_area + county_pop + log_dist_to_prisec +
log_pri_length_5000 + log_pri_length_10000 + log_pri_length_15000 +
log_pri_length_25000 + log_prisec_length_500 + log_prisec_length_1000 +
log_prisec_length_5000 + log_prisec_length_10000 + log_prisec_length_15000 +
log_prisec_length_25000 + log_nei_2008_pm25_sum_10000 + log_nei_2008_pm25_sum_15000 +
log_nei_2008_pm25_sum_25000 + log_nei_2008_pm10_sum_10000 +
log_nei_2008_pm10_sum_15000 + log_nei_2008_pm10_sum_25000 +
popdens_county + popdens_zcta + nohs + somehs + hs + somecollege +
associate + bachelor + grad + pov + hs_orless + urc2013 +
urc2006 + aod
<environment: 0x7f9f0883b268>
We can also view our recipe in more detail using the base summary() function.
# A tibble: 50 x 4
variable type role source
<chr> <chr> <chr> <chr>
1 id nominal id variable original
2 value numeric outcome original
3 fips nominal predictor original
4 lat numeric predictor original
5 lon numeric predictor original
6 state nominal predictor original
7 county nominal predictor original
8 city nominal predictor original
9 CMAQ numeric predictor original
10 zcta nominal predictor original
# … with 40 more rows
List the preprocessing steps using the step functions of the recipe package
The other thing the recipes package allows for is specifying pre-processing steps using a variety of step*() functions.

This link and this link show the many options for recipe step functions.
There are step functions for a variety of purposes:
- Imputation – which means filling in missing values based on the existing data
- Transformation – which means changing all values of a variable in the same way, typically to make it more normal or easier to interpret)
- Discretization – which means converting continuous values into discrete or nominal values - binning for example to reduce the number of possible levels) (However this is generally not advisable!)
- Encoding / Creating Dummy Variables – which means creating a numeric code for categorical variables More on Dummy Variables and one hot encoding
- Data type conversions – which means changing from integer to factor or numeric to date etc.
- Interaction term addition to the model – which means that we would be modeling for predictors that would influence the capacity of each other to predict the outcome
- Normalization – which means centering and scaling the data to a similar range of values
- Dimensionality Reduction/ Signal Extraction – which means mathematically obtaining a new smaller set of variables that capture the variation or signal in the original variables (ex. Principal Component Analysis and Independent Component Analysis)
- Filtering – Filtering options for removing variables (ex. remove variables that are highly correlated to others or remove variables with very little variance and therefore likely little predictive capacity)
- Row operations – which means performing functions on the values within the rows (ex. rearranging, filtering, imputing)
- Checking functions – Sanity checks to look for missing values, to look at the variable classes etc.
All of the step functions look like step_* except for the check functions which look like check_*.
There are several ways to select what variables to apply steps to:
1) tidyselect methods: contains(), matches(), starts_with(), ends_with(), everything(), num_range()
2) based on the type: all_nominal(), all_numeric() , has_type() 3) based on the role: all_predictors(), all_outcomes(), has_role() 4) name - use the actual name of the variable/variables of interest
Let’s try adding some steps to our recipe.
We might consider log transforming our population and area variables (that aren’t densities) - let’s take a look at the range of these variables.
$zcta_area
[1] 15459 8164820625
$zcta_pop
[1] 0 95397
$county_area
[1] 33703512 51947229509
$county_pop
[1] 783 9818605
We can see that the range for each of these variables is quite large, we can log transform this data using the step_log() function of the recipes package.
We would also want to potentially one hot encode some of our categorical variables so that they can be used with certain algorithms. We can do this with the step_dummy() function and the one_hot = TRUE argument. Our fips variable includes a numeric code for state and county - and therefore is essentially a proxy for county. Since we already have county, we will just use it and keep the fips id as another ID variable.
We can remove the fips variable from the predictors using update_role() to make sure that the role is no longer "predictor". We can make the role anything we want actually, so we will keep it something identifiable.
We might also want to remove variables that appear to be redundant and are highly correlated with others, as we know from our exploratory data analysis that many of our variables are correlated with one another. We can do this using the step_corr() function.
It is important to add the steps to the recipe in an order that makes sense just like with a cooking recipe.
simple_rec %<>%
#step_log(matches("_pop|_area")) %>%
update_role("fips", new_role = "county id") %>%
step_dummy(state, county, city, zcta) %>%
step_corr(all_numeric(), - CMAQ, - aod)%>%
step_nzv(all_numeric())
#step_dummy(state, county, city, zcta)
# step_dummy(state, county, city, zcta, one_hot = TRUE)
# check_new_values(all_predictors()) %>%
#check_range(all_predictors())
#can use step_rm() to remove predictors
simple_rec
Data Recipe
Inputs:
role #variables
county id 1
id variable 1
outcome 1
predictor 47
Operations:
Dummy variables from state, county, city, zcta
Correlation filter on all_numeric, -, CMAQ, -, aod
Sparse, unbalanced variable filter on all_numeric
OPTIONAL: Running the preprocessing (to see it)
The next major function of the recipes package is prep().
This function updates the recipe object based on the training data. It estimates parameters (estimating the required quantities and statistics required by the steps for the variables) for preprocessing and updates the model terms, as some of the predictors may be removed, this allows the recipe to be ready to use on other datasets. It doesn’t necessarily actually execute the preprocessing itself, however we will specify in argument for it to do this so that we can take a look at the preprocessed data.
There are some important arguments to know about: 1) training - you must supply a training data set to estimate parameters for preprocessing operations (recipe steps) - this may already be included in your recipe - as is the case for us 2) fresh - if TRUE - will retrain and estimate parameters for any previous steps that were already prepped if you add more steps to the recipe 3) verbose - if TRUE shows the progress as the steps are evaluated and the size of the preprocessed training set 4) retain - if TRUE then the preprocessed training set will be saved within the recipe (as template). This is good if you are likely to add more steps and don’t want to rerun the prep() on the previous steps. However this can make the recipe size large. This is necessary if you want to actually look at the preprocessed data.
oper 1 step dummy [training]
oper 2 step corr [training]
oper 3 step nzv [training]
The retained training set is ~ 0.26 Mb in memory.
[1] "var_info" "term_info" "steps" "template"
[5] "levels" "retained" "tr_info" "orig_lvls"
[9] "last_term_info"
There are also lots of useful things to checkout in the output of prep(). You can see: 1) the steps that were run
2) the variable info (var_info)
3) the model term_info 4) the new levels of the variables 5) the original levels of the variables orig_lvls
6) info about the training data set size and completeness (tr_info)
Note: You may see the prep.recipe() function in material that you read about the recipes package. This is referring to the prep() function of the recipes package.
Observations: 584
Variables: 36
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1055…
$ value <dbl> 9.597647, 10.800000, 11.212174, 12.3…
$ fips <fct> 1003, 1027, 1033, 1055, 1069, 1073, …
$ lat <dbl> 30.49800, 33.28126, 34.75878, 33.993…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 9.2417…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 1540…
$ zcta_pop <dbl> 27829, 5103, 9042, 20045, 30217, 901…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038,…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 5.1…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, …
$ county_pop <dbl> 182265, 13932, 54428, 104430, 101547…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 5.2614…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 9.0665…
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 12.013…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 8.7406…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 9.6278…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 11.…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 12.768…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, …
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 4.6783…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 75.3…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 1…
$ nohs <dbl> 3.3, 11.6, 7.3, 4.3, 5.8, 7.1, 2.7, …
$ somehs <dbl> 4.9, 19.1, 15.8, 13.3, 11.6, 17.1, 6…
$ hs <dbl> 25.1, 33.9, 30.6, 27.8, 29.8, 37.2, …
$ somecollege <dbl> 19.7, 18.8, 20.9, 29.2, 21.4, 23.5, …
$ associate <dbl> 8.2, 8.0, 7.6, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 8.8, 15.6, 25.5, 7.…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 45.4, 47.2, 61.4, …
$ urc2013 <dbl> 4, 6, 4, 4, 4, 1, 1, 1, 1, 1, 2, 3, …
$ aod <dbl> 37.36364, 34.81818, 36.00000, 43.416…
$ state_California <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ city_Not.in.a.city <dbl> 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, …
For easy comparison sake - here is our original data: #### {.scrollable }
Observations: 876
Variables: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6…
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, …
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.287…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85…
$ state <chr> "Alabama", "Alabama", "Alabama", "Al…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKal…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoal…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.5347…
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 3…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 3021…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038,…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, …
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430,…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.7214…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.5171…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409…
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173…
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.909…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.3101…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.5858…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.508…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.559…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.57312730…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.58191745…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.8876…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, …
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, …
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.1719…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 4…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 1…
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, …
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, …
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, …
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, …
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, …
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.083…
Notice how we only have 36 variables now instead of 50! Two of these are our ID variables (fips and the actual monitor ID (id)) and one is our outcome (value). Thus we only have 33 predictors now. We can also see that variables that we no longer have any categorical variables. Variables like state are gone and only state_California remains as it was the only state identity to have nonzero variance. We can see that California had the largest number of monitors compared to the other states. We can also see that there were more monitors listed as "Not in a city" than any city.
Note: Recall that you must specify retain = TRUE argument of the prep() function to use juice().
Observations: 292
Variables: 36
$ id <fct> 1049.1003, 1073.101, 1073.2006, 1089…
$ value <dbl> 11.659091, 13.114545, 12.228125, 12.…
$ fips <fct> 1049, 1073, 1073, 1089, 1103, 1121, …
$ lat <dbl> 34.28763, 33.54528, 33.38639, 34.687…
$ lon <dbl> -85.96830, -86.54917, -86.81667, -86…
$ CMAQ <dbl> 8.534772, 9.303766, 10.235612, 9.343…
$ zcta_area <dbl> 203836235, 148994881, 56063756, 4696…
$ zcta_pop <dbl> 8300, 14212, 32390, 21297, 30545, 77…
$ imp_a500 <dbl> 5.78200692, 0.06055363, 42.42820069,…
$ imp_a15000 <dbl> 0.9730444, 2.9956557, 12.7487614, 10…
$ county_area <dbl> 2012662359, 2878192209, 2878192209, …
$ county_pop <dbl> 71109, 658466, 658466, 334811, 11949…
$ log_dist_to_prisec <dbl> 3.721489, 7.301545, 4.721755, 4.6595…
$ log_pri_length_5000 <dbl> 8.517193, 9.683336, 10.737240, 8.517…
$ log_pri_length_25000 <dbl> 11.90959, 12.53777, 12.99669, 11.473…
$ log_prisec_length_500 <dbl> 7.310155, 6.214608, 7.528913, 8.7605…
$ log_prisec_length_1000 <dbl> 8.585843, 7.600902, 9.342290, 9.5431…
$ log_prisec_length_5000 <dbl> 10.214200, 11.262645, 11.713190, 11.…
$ log_prisec_length_10000 <dbl> 11.50894, 12.14101, 12.53899, 12.684…
$ log_nei_2008_pm10_sum_15000 <dbl> 3.3500444, 6.6241114, 5.8268686, 3.8…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.1719202, 7.5490587, 8.8205542, 5.2…
$ popdens_county <dbl> 35.330814, 228.777633, 228.777633, 1…
$ popdens_zcta <dbl> 40.718962, 95.385827, 577.735106, 45…
$ nohs <dbl> 14.3, 7.2, 0.8, 1.2, 4.8, 16.7, 19.1…
$ somehs <dbl> 16.7, 12.2, 2.6, 3.1, 7.8, 33.3, 15.…
$ hs <dbl> 35.0, 32.2, 12.9, 15.1, 28.7, 37.5, …
$ somecollege <dbl> 14.9, 19.0, 17.9, 20.5, 25.0, 12.5, …
$ associate <dbl> 5.5, 6.8, 5.2, 6.5, 7.5, 0.0, 6.0, 8…
$ bachelor <dbl> 7.9, 14.8, 35.5, 30.4, 18.2, 0.0, 10…
$ grad <dbl> 5.8, 7.7, 25.2, 23.3, 8.0, 0.0, 4.1,…
$ pov <dbl> 13.8, 10.5, 2.1, 5.2, 8.3, 18.8, 21.…
$ hs_orless <dbl> 66.0, 51.6, 16.3, 19.4, 41.3, 87.5, …
$ urc2013 <dbl> 6, 1, 1, 3, 4, 5, 1, 2, 5, 4, 4, 6, …
$ aod <dbl> 33.08333, 42.45455, 44.25000, 42.416…
$ state_California <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ city_Not.in.a.city <dbl> NA, NA, NA, NA, NA, NA, 0, NA, NA, N…
bake() takes a trained recipe and applies the operations to a data set to create a design matrix. for example: it applies the centering to new data sets using these means used to create the recipe
Note: if you use the skip option for some of the preprocessing steps, be careful. juice() will show all of the results ignoring skip = TRUE. bake() will not necessarily conduct these steps on the new data.
Specifying the Model
So far we have used rsample to split the data and recipes to assign variable and to specify and prep our preprocessing (as well as to optionally extract the preprocessed data).
We will now use the parsnip package (which is similar to the previous caret package - and hence why it is named after the vegetable) to specify our model.
There are four aspects to define about our model:
1) the type of model (using specific funtions in parsnip like rand_forest(), logistic_reg() etc.)
2) the mode of learning - classification or regression (using the set_mode() function)
3) the package or engine that we will use to implement the type of model selected (using the set_engine() function)
4) any arguments necessary for the model/package selected (using the set_args()function - for example the mtry = argument for random forest which is the number of variables to be used as options for splitting at each tree node)
We are going to start our analysis with a linear regression but we will demonstrate how we can try different models.
The first thing we do is define what type of model we would like to use. See here for modeling [options]in parsnip.
Linear Regression Model Specification (regression)
OK. So far all we have told parsnip is we want to use a linear regression… Let’s tell parsnip more about what we want.
We would like to use the ordinary least squares method to fit our linear regression. So we will tell parsnip that we want to use the lm package to implement our linear regression (there are many options actually- such as rstan glmnet, keras, and sparklyr). We will do so by using the set_engine() function of the parsnip package.
Linear Regression Model Specification (regression)
Computational engine: lm
In some cases some packages can do either classification or prediction, so it is a good idea to specify which mode you intend to perform. You can do this with the set_mode() function of the parsnip package, by using either set_mode("classification") or set_mode("regression").
Linear Regression Model Specification (regression)
Computational engine: lm
Fitting the Model with workflows and parsnip
To fit our model we could use parsnip and then assess our fit using the yardstick package.
However a newer package called workflows allows us to keep track of both our preprocessing steps and our model specification. It also allows us to implement fancier optimizations in an automated way and it is currently being developed to also handle post-processing operations, so it is good to learn about it!
So we will now create a workflow with the recipe (our preprocessing specifications) that we made and the model that we just specified.
First we use the workflow() function of the workflows package to create a workflow.
Then we add our recipe with the add_recipe() function and we add our model with the add_model() function of the workflows package.
Note: We do not need to actually prep our recipe before using workflows!
══ Workflow ═════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()
── Preprocessor ─────────────────────────────────────────────────────────────────────────────
3 Recipe Steps
● step_dummy()
● step_corr()
● step_nzv()
── Model ────────────────────────────────────────────────────────────────────────────────────
Linear Regression Model Specification (regression)
Computational engine: lm
Ah, nice. Notice how it tells us about both our preprocessing steps and our model specifications.
Now we can prepare the recipe (estimate the parameters) and fit the model to our training data all at once. Printing the output we can see the coefficients of the model.
══ Workflow [trained] ═══════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: linear_reg()
── Preprocessor ─────────────────────────────────────────────────────────────────────────────
3 Recipe Steps
● step_dummy()
● step_corr()
● step_nzv()
── Model ────────────────────────────────────────────────────────────────────────────────────
Call:
stats::lm(formula = formula, data = data)
Coefficients:
(Intercept) lat
2.221e+02 3.773e-02
lon CMAQ
3.023e-02 2.896e-01
zcta_area zcta_pop
3.592e-10 7.988e-06
imp_a500 imp_a15000
6.543e-03 -1.252e-03
county_area county_pop
-2.241e-11 -2.052e-07
log_dist_to_prisec log_pri_length_5000
4.182e-02 -2.207e-01
log_pri_length_25000 log_prisec_length_500
9.277e-02 2.651e-01
log_prisec_length_1000 log_prisec_length_5000
-1.654e-02 4.451e-01
log_prisec_length_10000 log_nei_2008_pm10_sum_15000
1.510e-01 1.029e-01
log_nei_2008_pm10_sum_25000 popdens_county
6.448e-02 -3.905e-05
popdens_zcta nohs
-2.098e-05 -2.195e+00
somehs hs
-2.232e+00 -2.235e+00
somecollege associate
-2.237e+00 -2.237e+00
bachelor grad
-2.239e+00 -2.248e+00
pov hs_orless
5.400e-03 NA
urc2013 aod
1.848e-01 2.521e-02
state_California city_Not.in.a.city
3.509e+00 4.137e-01
Otherwise we could have done this without the workflows package:
Looking at model fit with broom
The broom package allows for an easy/tidy way to look at the fitted model:
tidy() grabs the coefficients from the model
glance() summarizes the model fit
augment() gives a 150 row observation level summary
These broom functions currently only work with parsnip objects not raw workflows objects. To use these functions with workflows we need to first use the pull_workflow_fit() function.
# A tibble: 584 x 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 9.60 NaN NaN NaN
2 id1027.0001 1.20 NaN NaN NaN
3 id1033.1002 1.61 NaN NaN NaN
4 id1055.001 2.78 NaN NaN NaN
5 id1069.0003 0.911 NaN NaN NaN
6 id1073.0023 5.99 NaN NaN NaN
7 id1073.1005 2.80 NaN NaN NaN
8 id1073.1009 1.51 NaN NaN NaN
9 id1073.2003 4.95 NaN NaN NaN
10 id1073.5002 2.35 NaN NaN NaN
# … with 574 more rows
# A tibble: 1 x 11
r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
<dbl> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 1 NaN NaN NaN NaN 584 Inf -Inf -Inf
# … with 2 more variables: deviance <dbl>, df.residual <int>
# A tibble: 584 x 41
value id fips lat lon CMAQ zcta_area zcta_pop imp_a500
<dbl> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 9.60 1003… 1003 30.5 -87.9 8.10 190980522 27829 0.0173
2 10.8 1027… 1027 33.3 -85.8 9.77 374132430 5103 1.97
3 11.2 1033… 1033 34.8 -87.7 9.40 16716984 9042 19.2
4 12.4 1055… 1055 34.0 -86.0 9.24 154069359 20045 16.5
5 10.5 1069… 1069 31.2 -85.4 9.12 162685124 30217 19.1
6 15.6 1073… 1073 33.6 -86.8 10.2 26929603 9010 41.8
7 12.4 1073… 1073 33.3 -87.0 10.2 166239542 16140 1.70
8 11.1 1073… 1073 33.5 -87.3 8.16 385566685 3699 0
9 14.6 1073… 1073 33.5 -86.9 10.2 10636977 11458 43.6
10 12.0 1073… 1073 33.7 -86.7 9.30 150661846 21725 1.48
# … with 574 more rows, and 32 more variables: imp_a15000 <dbl>,
# county_area <dbl>, county_pop <dbl>, log_dist_to_prisec <dbl>,
# log_pri_length_5000 <dbl>, log_pri_length_25000 <dbl>,
# log_prisec_length_500 <dbl>, log_prisec_length_1000 <dbl>,
# log_prisec_length_5000 <dbl>, log_prisec_length_10000 <dbl>,
# log_nei_2008_pm10_sum_15000 <dbl>, log_nei_2008_pm10_sum_25000 <dbl>,
# popdens_county <dbl>, popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>,
# hs <dbl>, somecollege <dbl>, associate <dbl>, bachelor <dbl>,
# grad <dbl>, pov <dbl>, hs_orless <dbl>, urc2013 <dbl>, aod <dbl>,
# state_California <dbl>, city_Not.in.a.city <dbl>, .fitted <dbl>,
# .se.fit <dbl>, .resid <dbl>, .hat <dbl>, .sigma <dbl>
# A tibble: 33 x 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 2.22e+ 2 1.20e+ 2 1.85 6.51e- 2
2 lat 3.77e- 2 2.45e- 2 1.54 1.24e- 1
3 lon 3.02e- 2 9.31e- 3 3.25 1.23e- 3
4 CMAQ 2.90e- 1 4.29e- 2 6.75 3.66e-11
5 zcta_area 3.59e-10 3.04e-10 1.18 2.38e- 1
6 zcta_pop 7.99e- 6 5.55e- 6 1.44 1.50e- 1
7 imp_a500 6.54e- 3 7.49e- 3 0.874 3.82e- 1
8 imp_a15000 -1.25e- 3 1.19e- 2 -0.105 9.16e- 1
9 county_area -2.24e-11 1.63e-11 -1.38 1.69e- 1
10 county_pop -2.05e- 7 9.31e- 8 -2.20 2.79e- 2
# … with 23 more rows
OK, so we have fit our model on our training data, which means we have created a model to predict values of air pollution based on the predictors that we have included. Yay!
At this point we could take a look at the accuracy of our model performance, but we will only have one reference point: our testing dataset. And we haven’t done any tuning of our model or cross validation… so generally speaking you should not do this.
However if you were short on time you could continue like this.
need tune_*(), fit_resamples() or last_fit() to get any assessment of fit.
We could stop here and use the yardstick package to evaluate performance. First we would want to fit the model with hmmm not sure if I will do this or just skip and use tune even if we dont have any tuning??
Using parsnip we need to use the baked data testing data… or not???
# A tibble: 292 x 3
.pred value fips
<dbl> <dbl> <fct>
1 NA 11.7 1049
2 NA 13.1 1073
3 NA 12.2 1073
4 NA 12.2 1089
5 NA 11.4 1103
6 NA 12.2 1121
7 9.52 10.9 4013
8 NA 10.6 4021
9 NA 14.1 4023
10 NA 5.83 4025
# … with 282 more rows
Say we were done optimizing our parameters we could then use the last_fit() function of the workflows package.
However we would really want to tune parameters and use cross validation for this.
yardstick can’t talk directly to workflows… need tune for that…
Cross validation sample splitting
We will use the rsample package again in order to further implement what are called cross validation techniques. This is also called resampling or repartioning. Note: we are not actually getting new samples from the underlying distribution so the term resampling is a bit of a misnomer.
Cross validation splits our training data into multiple training data sets to allow for an assessment of the accuracy of the model.
Here is a visualization of the concept for cross validation/resampling/repartitioning from Max Kuhn:

Technically creating our testing and training set out of our original training data is sometimes considered a form of cross validation called the holdout method. As we just learned this can give us a better sense of the accuracy of our data in a more generalizable way.
However, we can do a better job of optimizing our model for accuracy if we also perform another type of cross validation on the newly defined training set that we just created. There are many cross validation methods and most can be easily implemented using rsamples package. We will use a very popular method called either k-fold or v-fold cross validation.
This method involves essentially preforming the hold out method iteratively with the training data.
First the training set is divided into k or v equally sized smaller pieces.
Then the model is trained on the model on k-1 or v-1 subsets of the data iteratively (removing a different v or k untill all possible k-1 or v-1 sets have been evaluated) to get a sense of the performance of the model. This is really useful for fine tuning specific aspects of the model in a process called model tuning.
Here is a visualization of how the folds are created:

Note: People typically ignore spatial dependence with cross validation of air pollution monitoring data in the air pollution field, so we will do the same. However, it might make sense to leave out blocks of monitors rather than random individual monitors to help account for some spatial dependence.
The vfold_cv() function of the rsample package can be used to parse the training data into folds for k-fold/v-fold cross validation.
The v argument specifies the number of folds to create. The repeats argument specifies if any samples should be repeated across folds - defualt is FALSE The strata argument specifies a variable to stratify samples across folds (just like in initial_split()).
Again because these are created at random, we need to use the base set.seed() function in order to obtain the same results each time we knit this document.
# 10-fold cross-validation
# A tibble: 10 x 2
splits id
<named list> <chr>
1 <split [525/59]> Fold01
2 <split [525/59]> Fold02
3 <split [525/59]> Fold03
4 <split [525/59]> Fold04
5 <split [526/58]> Fold05
6 <split [526/58]> Fold06
7 <split [526/58]> Fold07
8 <split [526/58]> Fold08
9 <split [526/58]> Fold09
10 <split [526/58]> Fold10
<525/59/584>
<525/59/584>
Once the folds are created they can be used to evaluate peformance by fitting the model to each of the resamples that we created:

We can fit the model to our cross validation folds using the fit_resamples() function of the tune package, by specifying our workflow object and the cross validation fold object we just created. See here for more information.
We can now take a look at various metrics of performance based on the fit of our 10 cross validation “resamples”. To do this we will use the show_best() function of the tune package.
# A tibble: 1 x 5
.metric .estimator mean n std_err
<chr> <chr> <dbl> <int> <dbl>
1 rmse standard 2.08 10 0.147
Tuning
Now let’s try some tuning.
Let’s take a closer look at how the monitor values vary with latitude and longitude.

We can see that there does not appear to be a single linear relationship for either of these predictors. Thus we might want to think about using splines or this(https://towardsdatascience.com/numerical-interpolation-natural-cubic-spline-52c1157b98ac) or just this(https://tidymodels.github.io/tune/articles/getting_started.html) or this(https://www.psych.mcgill.ca/misc/fda/ex-basis-b1.html) to model the relationship in our training data more closely. For example for the latitude plot (left) if we had 2 lines and one breakpoint called a knot around 40, with the first line having a positive slope and the second with a negative slope this would fit the data more similarly to the blue line shown in the figure.
We can tune for the number of knots by using a step function in the recipes package called step_ns() where ns stands for natural splines. In order to tune for the number of knots or degrees of freedom, we can set the deg_free argument to tune(). This is helpful, becuase we aren’t exactly sure how closely we should be following the relationship with the value and our longitude and latitude data in our training data to achieve good accuracy yet keep our model generalizable for other data.
This is when our cross validation methods become really handy. We can test out different values for the deg_free argument and see how our model performance varies across our training folds to try to find the optimal value.
We will update our recipe to add these steps. It is a good idea to do this for individual predictors because you can name each with the tune argument so that you can keep track of it later. We can see what we intend to tune with the parameters() function of the dials package.
See here for more information about implementing this in tidymodels.
Collection of 2 parameters for tuning
id parameter type object class
lon df deg_free nparam[+]
lat df deg_free nparam[+]
Genearlly you could use the grid_*() functions of the dials package to create the different combinations of degrees of freedom to test for both variables to optimize the model. In our case we can visably see that if we add more than say 4 or 5 degrees of freedom we will likely overfit the data. So instead of using these functions we will create our own grid using the base seq() and expand.grid() functions.
lon df lat df
1 1 1
2 3 1
3 5 1
4 1 3
5 3 3
6 5 3
7 1 5
8 3 5
9 5 5
Now we will tune this hyper-parameter (degrees of freedom) for both the lat and lon variables using our cross validation folds. To do this we will use the tune_grid() function of the tune package.
# 10-fold cross-validation
# A tibble: 10 x 4
splits id .metrics .notes
* <list> <chr> <list> <list>
1 <split [525/59]> Fold01 <tibble [18 × 5]> <tibble [18 × 1]>
2 <split [525/59]> Fold02 <tibble [18 × 5]> <tibble [18 × 1]>
3 <split [525/59]> Fold03 <tibble [18 × 5]> <tibble [18 × 1]>
4 <split [525/59]> Fold04 <tibble [18 × 5]> <tibble [18 × 1]>
5 <split [526/58]> Fold05 <tibble [18 × 5]> <tibble [18 × 1]>
6 <split [526/58]> Fold06 <tibble [18 × 5]> <tibble [18 × 1]>
7 <split [526/58]> Fold07 <tibble [18 × 5]> <tibble [18 × 1]>
8 <split [526/58]> Fold08 <tibble [18 × 5]> <tibble [18 × 1]>
9 <split [526/58]> Fold09 <tibble [18 × 5]> <tibble [18 × 1]>
10 <split [526/58]> Fold10 <tibble [18 × 5]> <tibble [18 × 1]>
# A tibble: 18 x 7
`lon df` `lat df` .metric .estimator mean n std_err
<dbl> <dbl> <chr> <chr> <dbl> <int> <dbl>
1 1 1 rmse standard 2.08 10 0.147
2 1 1 rsq standard 0.433 10 0.0504
3 1 3 rmse standard 1.99 10 0.149
4 1 3 rsq standard 0.483 10 0.0483
5 1 5 rmse standard 2.00 10 0.151
6 1 5 rsq standard 0.477 10 0.0475
7 3 1 rmse standard 2.00 10 0.160
8 3 1 rsq standard 0.475 10 0.0557
9 3 3 rmse standard 1.91 10 0.159
10 3 3 rsq standard 0.519 10 0.0508
11 3 5 rmse standard 1.90 10 0.159
12 3 5 rsq standard 0.526 10 0.0514
13 5 1 rmse standard 2.00 10 0.162
14 5 1 rsq standard 0.469 10 0.0576
15 5 3 rmse standard 1.92 10 0.166
16 5 3 rsq standard 0.512 10 0.0565
17 5 5 rmse standard 1.90 10 0.171
18 5 5 rsq standard 0.519 10 0.0613
# A tibble: 18 x 7
`lon df` `lat df` .metric .estimator mean n std_err
<dbl> <dbl> <chr> <chr> <dbl> <int> <dbl>
1 1 1 rmse standard 2.08 10 0.147
2 1 1 rsq standard 0.433 10 0.0504
3 1 3 rmse standard 1.99 10 0.149
4 1 3 rsq standard 0.483 10 0.0483
5 1 5 rmse standard 2.00 10 0.151
6 1 5 rsq standard 0.477 10 0.0475
7 3 1 rmse standard 2.00 10 0.160
8 3 1 rsq standard 0.475 10 0.0557
9 3 3 rmse standard 1.91 10 0.159
10 3 3 rsq standard 0.519 10 0.0508
11 3 5 rmse standard 1.90 10 0.159
12 3 5 rsq standard 0.526 10 0.0514
13 5 1 rmse standard 2.00 10 0.162
14 5 1 rsq standard 0.469 10 0.0576
15 5 3 rmse standard 1.92 10 0.166
16 5 3 rsq standard 0.512 10 0.0565
17 5 5 rmse standard 1.90 10 0.171
18 5 5 rsq standard 0.519 10 0.0613
# A tibble: 1 x 7
`lon df` `lat df` .metric .estimator mean n std_err
<dbl> <dbl> <chr> <chr> <dbl> <int> <dbl>
1 5 5 rmse standard 1.90 10 0.171
Let’s review everything:

check_new_values: This check will break the bake function if any of the checked columns does contain values it did not contain when prep was called on the recipe. If the check passes, nothing is changed to the data
check_range creates a specification of a recipe check that will check if the range of a numeric variable changed in the new data.
parameter vs hyperparameter
prepper for cross validation?
great blog about cross validation etc https://towardsdatascience.com/train-test-split-and-cross-validation-in-python-80b61beca4b6
LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBQcmVkaWN0aW5nIEFubnVhbCBBaXIgUG9sbHV0aW9uICIKY3NzOiBzdHlsZS5jc3MKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBzZWxmX2NvbnRhaW5lZDogeWVzCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKCi0tLQo8c3R5bGU+CiNUT0MgewogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL2ltZy9sb2dvLmpwZyIpOwogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsKICBwYWRkaW5nLXRvcDogMjQwcHggIWltcG9ydGFudDsKICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Owp9Cjwvc3R5bGU+CgoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGluY2x1ZGUgPSBUUlVFLCBjb21tZW50ID0gTkEsIGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgb3V0LndpZHRoID0gJzkwJScpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShrbml0cikKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5wbG90LnBuZyIpKQpgYGAKCiMjIyMKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgTW90aXZhdGlvbgpBIHZhcmlldHkgb2YgZGlmZmVyZW50IHNvdXJjZXMgY29udHJpYnV0ZSBkaWZmZXJlbnQgdHlwZXMgb2YgcG9sbHV0YW50cyB0byB3aGF0IHdlIGNhbGwgYWlyIHBvbGx1dGlvbi4gClNvbWUgc291cmNlcyBhcmUgbmF0dXJhbCB3aGlsZSBvdGhlcnMgYXJlIGFudGhyb3BvZ2VuaWMgKGh1bWFuIGRlcml2ZWQpOgoKPHAgYWxpZ249ImNlbnRlciI+CiAgPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3Lm5wcy5nb3Yvc3ViamVjdHMvYWlyL2ltYWdlcy9Tb3VyY2VzX0dyYXBoaWNfSHVnZS5qcGc/bWF4d2lkdGg9MTIwMCZtYXhoZWlnaHQ9MTIwMCZhdXRvcm90YXRlPWZhbHNlIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3NhPWkmdXJsPWh0dHBzJTNBJTJGJTJGd3d3Lm5wcy5nb3YlMkZzdWJqZWN0cyUyRmFpciUyRnNvdXJjZXMuaHRtJnBzaWc9QU92VmF3MnY3QVZ4U0Y4WlNBUEVoTnVkVnRiTiZ1c3Q9MTU4NTc3MDk2NjIxNzAwMCZzb3VyY2U9aW1hZ2VzJmNkPXZmZSZ2ZWQ9MENBSVFqUnhxRndvVENQRE42NnFfeGVnQ0ZRQUFBQUFkQUFBQUFCQUQpXQoKIyMjIyBNYWpvciB0eXBlcyBvZiBhaXIgcG9sbHV0YW50cwoKMSkgKipHYXNlb3VzKiogLSBDYXJib24gTW9ub3hpZGUgKENPKSwgT3pvbmUgKE9+M34pLCBOaXRyb2dlbiBPeGlkZXMoTk8sIE5PfjJ+KSwgU3VscGhlciBEaW94aWRlIChTT34yfikKMikgKipQYXJ0aWN1bGF0ZSoqIC0gc21hbGwgbGlxdWlkcyBhbmQgc29saWRzIHN1c3BlbmRlZCBpbiB0aGUgYWlyIChpbmNsdWRlcyBsZWFkLSBjYW4gaW5jbHVkZSBjZXJ0YWluIHR5cGVzIG9mIGR1c3QpCjMpICoqRHVzdCoqIC0gc21hbGwgc29saWRzIChsYXJnZXIgdGhhbiBwYXJ0aWN1bGF0ZXMpIHRoYXQgY2FuIGJlIHN1c3BlbmRlZCBpbiB0aGUgYWlyIGZvciBzb21lIHRpbWUgYnV0IGV2ZW50dWFsbHkgc2V0dGxlCjQpICoqQmlvbG9naWNhbCoqIC0gcG9sbGVuLCBiYWN0ZXJpYSwgdmlydXNlcywgbW9sZCBzcG9yZXMKClNlZSBbaGVyZV0paHR0cDovL3d3dy5yZWRsb2dlbnYuY29tL3dvcmtlci1zYWZldHkvcGFydC0xLWR1c3QtYW5kLXBhcnRpY3VsYXRlLW1hdHRlcikgZm9yIG1vcmUgZGV0YWlsIG9uIHRoZSB0eXBlcyBvZiBwb2xsdXRhbnRzIGluIHRoZSBhaXIuCgoKIyMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gCgpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4KClRoZXJlIGFyZSAzIG1ham9yIGNhdGVnb3JpZXM6CgoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdGVyIC0gaGFzIGRpYW1ldGVyIG9mID4xMCBtaWNyb21ldGVycyAoMTAgwrVtKSAKCjIpICoqQ29hcnNlKiogUGFydGljdWxhdGUgTWF0ZXIgKGNhbGxlZCAqKlBNfjEwLTIuNX4qKikgLSBoYXMgZGlhbWV0ZXIgb2YgYmV0d2VlbiAyLjUgwrVtIGFuZCAxMCDCtW0KCjMpICoqRmluZSoqIFBhcnRpY3VsYXRlIE1hdGVyIChjYWxsZWQgKipQTX4yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIDwgMi41IMK1bSAKCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdGVyIDwxMCDCtW0gKGJvdGggY29hcnNlIGFuZCBmaW5lIHBhcnRpY3VsYXRlIG1hdGVyKQoKSGVyZSB5b3UgY2FuIHNlZSBob3cgdGhlc2Ugc2l6ZXMgY29tcGFyZSB3aXRoIGEgaHVtYW4gaGFpcjoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjYwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJwbTIuNV9zY2FsZV9ncmFwaGljLWNvbG9yXzIuanBnIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3MpXQoKPCEtLSA8cCBhbGlnbj0iY2VudGVyIj4gLS0+CjwhLS0gICA8aW1nIHdpZHRoPSI1MDAiIHNyYz0iaHR0cHM6Ly93d3cuc2Vuc2lyaW9uLmNvbS9pbWFnZXMvc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZS1maWd1cmUtMS1jZGQ3MC5qcGciPiAtLT4KPCEtLSA8L3A+IC0tPgoKCjx1PlRoZSBmb2xsb3dpbmcgcGxvdCBhbmQgdGFibGUgc2hvdyB0aGUgcmVsYXRpdmUgc2l6ZXMgb2YgdGhlc2UgZGlmZmVyZW50IHBvbGx1dGFudHMgaW4gbWljcm9tZXRlcnMowrVtKTo8L3U+Cgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy90aHVtYi9kL2RmL0FpcmJvcm5lLXBhcnRpY3VsYXRlLXNpemUtY2hhcnQuc3ZnLzgwMHB4LUFpcmJvcm5lLXBhcnRpY3VsYXRlLXNpemUtY2hhcnQuc3ZnLnBuZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9QYXJ0aWN1bGF0ZXMpXQoKCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAyLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpXQoKCjx1PlRoaXMgdGFibGUgc2hvd3MgaG93IGRlZXBseSBzb21lIG9mIHRoZSBzbWFsbGVyIGZpbmUgcGFydGljbGVzIGNhbiBwZW5ldHJhdGUgd2l0aGluIHRoZSBodW1hbiBib2R5OjwvdT4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjUwMCIgc3JjPSJodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvZmlsZXMvQXJ0aWNsZXMvNTA1NTcwL2ZwdWJoLTA4LTAwMDE0LUhUTUwvaW1hZ2VfbS9mcHViaC0wOC0wMDAxNC10MDAxLmpwZyI+CjwvcD4KCiMjIyMjIFtbc291cmNlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpXQoKCiMjIyMgTmVnYXRpdmUgSW1wYWN0IG9mIFBhcnRpY3VsYXRlIEV4cG9zdXJlIG9uIEhlYWx0aCAKCkV4cG9zdXJlIHRvIGFpciBwb2xsdXRpb24gaXMgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBbbW9ydGFsaXR5XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM1NzgzMTg2Lyl7dGFyZ2V0PSJfYmxhbmsifSBpbiBvbGRlciBhZHVsdHMgYW5kIGlzIGtub3duIHRvIGJlIGEgcmlzayBmYWN0b3IgZm9yIG1hbnkgZGlzZWFzZXMgYW5kIGNvbmRpdGlvbnMgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCjEpIFtBc3RobWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzI5MjQzOTM3KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIHdhcyBmb3VuZCB0byBiZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIHJhdGVzIG9mIGFzdGhtYSBpbiBjaGlsZHJlbgoyKSBbSW5mbGFtbWF0aW9uIGluIHR5cGUgMSBkaWFiZXRlc10oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE0MTk3NjUpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikgZnJvbSB0cmFmZmljLXJlbGF0ZWQgYWlyIHBvbGx1dGlvbiB3YXMgYXNzb2NpYXRlZCB3aXRoIGluY3JlYXNlZCBtZWFzdXJlcyBvZiBpbmZsYW1tYXRvcnkgbWFya2VycyBpbiB5b3V0aHMgd2l0aCB0eXBlIDEgZGlhYmV0ZXMKMykgW0x1bmcgZnVuY3Rpb24gYW5kIGVtcGh5c2VtYV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE0MDgxMzUpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgY29uY2VudHJhdGlvbnMgb2Ygb3pvbmUgKE9+M34pLCBuaXRyb2dlbiBveGlkZXMgKE5Pfnh+KSwgYmxhY2sgY2FyYm9uLCBhbmQgZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAqKlBNfjIuNX4qKiAsIGF0IHN0dWR5IGJhc2VsaW5lIHdlcmUgc2lnbmlmaWNhbnRseSBhc3NvY2lhdGVkIHdpdGggZ3JlYXRlciBpbmNyZWFzZXMgaW4gcGVyY2VudCBlbXBoeXNlbWEgcGVyIDEwIHllYXJzIAo0KSBbTG93IGJpcnRod2VpZ2h0XShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTM4NjY0Myl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUoKipQTX4yLjV+KiopIHdhcyBhc3NvY2lhdGVkIHdpdGggbG93ZXIgYmlydGggd2VpZ2h0IGluIGZ1bGwtdGVybSBsaXZlIGJpcnRocwo1KSBbVmlyYWwgSW5mZWN0aW9uXShodHRwczovL3d3dy50YW5kZm9ubGluZS5jb20vZG9pL2Z1bGwvMTAuMTA4MC8wODk1ODM3MDcwMTY2NTQzNCl7dGFyZ2V0PSJfYmxhbmsifSAtIGhpZ2hlciByYXRlcyBvZiBpbmZlY3Rpb24gYW5kIGluY3JlYXNlZCBzZXZlcml0eSBvZiBpbmZlY3Rpb24gYXJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgZXhwb3N1cmVzIHRvIHBvbGx1dGlvbiBsZXZlbHMgaW5jbHVkaW5nIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKQoKU2VlIHRoaXMgW3JldmlldyBhcnRpY2xlXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgc291cmNlcyBvZiBhaXIgcG9sbHV0aW9uIGFuZCB0aGUgaW5mbHVlbmNlIG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoLgoKIyMjIyBTcGFyc2UgTW9uaXRvcmluZyBpcyBQcm9ibGVtYXRpYyBmb3IgUHVibGljIEhlYWx0aAoKSGlzdG9yaWNhbGx5IGVwaWRlbWlvbG9naWNhbCBzdHVkaWVzIHdvdWxkIGFzc2VzcyB0aGUgaW5mbHVlbmNlIG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoIG91dGNvbWVzIGJ5IHJlbHlpbmcgb24gYSBudW1iZXIgb2YgbW9uaXRvcnMgbG9jYXRlZCBhcm91bmQgdGhlIGNvdW50cnkuIEhvd2V2ZXIgYXMgY2FuIGJlIHNlZW4gaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUsIHRoZXNlIG1vbml0b3JzIHJlbWFpbiB0byBiZSByZWxhdGl2ZWx5IHNwYXJzZSBpbiBjZXJ0YWluIHJlZ2lvbnMgb2YgdGhlIGNvdW50cnkuIEZ1cnRoZXJtb3JlLCBkcmFtYXRpYyBkaWZmZXJlbmNlcyBpbiBwb2xsdXRpb24gcmF0ZXMgY2FuIGJlIHNlZW4gZXZlbiB3aXRoaW4gdGhlIHNhbWUgY2l0eS4KCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjQwMCIgc3JjPSJodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM0MTM3MjcyL2Jpbi8xNDc2LTA2OVgtMTMtNjMtMS5qcGciPgo8L3A+CgojIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpXQoKVGhpcyBsYWNrIG9mIGdyYW51bGFyaXR5IGluIGFpciBwb2xsdXRpb24gbW9uaXRvcmluZyBoYXMgaGluZGVyZWQgb3VyIGFiaWxpdHkgdG8gZGlzY2VybiB0aGUgZnVsbCBpbXBhY3Qgb2YgYWlyIHBvbGx1dGlvbiBvbiBoZWFsdGggYW5kIHRvIGlkZW50aWZ5IGF0LXJpc2sgbG9jYXRpb25zLiAKCgojIyMjIE1hY2hpbmUgTGVhcm5pbmcgT2ZmZXJzIGEgU29sdXRpb24KCkFuIFthcnRpY2xlXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gdGhlICpFbnZpcm9ubWVudGFsIEhlYWx0aCogam91cm5hbCBkZWFsdCB3aXRoIHRoaXMgaXNzdWUgYnkgdXNpbmcgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHJvYWQgZGVuc2l0eSwgYW1vbmcgb3RoZXIgZmVhdHVyZXMgdG8gbW9kZWwgb3IgcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBhdCBhIG1vcmUgbG9jYWxpemVkIHNjYWxlIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcy4gCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGhlcGFwZXIucG5nIikpCmBgYAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KWWFub3NreSwgSi4gRC4gZXQgYWwuIFNwYXRpby10ZW1wb3JhbCBtb2RlbGluZyBvZiBwYXJ0aWN1bGF0ZSBhaXIgcG9sbHV0aW9uIGluIHRoZSBjb250ZXJtaW5vdXMgVW5pdGVkIFN0YXRlcyB1c2luZyBnZW9ncmFwaGljIGFuZCBtZXRlb3JvbG9naWNhbCBwcmVkaWN0b3JzLiAqRW52aXJvbiBIZWFsdGgqIDEzLCA2MyAoMjAxNCkuCgojIyMjCgpUaGUgYXV0aG9ycyBvZiB0aGlzIGFydGljbGUgc3RhdGUgdGhhdDoKCj4gIkV4cG9zdXJlIHRvIGF0bW9zcGhlcmljIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0pIHJlbWFpbnMgYW4gaW1wb3J0YW50IHB1YmxpYyBoZWFsdGggY29uY2VybiwKYWx0aG91Z2ggaXQgcmVtYWlucyBkaWZmaWN1bHQgdG8gcXVhbnRpZnkgYWNjdXJhdGVseSBhY3Jvc3MgbGFyZ2UgZ2VvZ3JhcGhpYyBhcmVhcyB3aXRoIHN1ZmZpY2llbnRseSBoaWdoIHNwYXRpYWwKcmVzb2x1dGlvbi4gUmVjZW50IGVwaWRlbWlvbG9naWMgYW5hbHlzZXMgaGF2ZSBkZW1vbnN0cmF0ZWQgdGhlIGltcG9ydGFuY2Ugb2Ygc3BhdGlhbGx5LSBhbmQgdGVtcG9yYWxseS1yZXNvbHZlZApleHBvc3VyZSBlc3RpbWF0ZXMsIHdoaWNoIHNob3cgbGFyZ2VyIFBNLW1lZGlhdGVkIGhlYWx0aCBlZmZlY3RzIGFzIGNvbXBhcmVkIHRvIG5lYXJlc3QgbW9uaXRvciBvcgpjb3VudHktc3BlY2lmaWMgYW1iaWVudCBjb25jZW50cmF0aW9ucy4iIAoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjcwMCBweCIsIGV2YWwgPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImRlYXRocy5wbmciKSkKYGBgCgpUaGUgYXJ0aWNsZSBhYm92ZSBleHBsYWlucyB0aGF0IG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIHdoZW4gdHJhZGl0aW9uYWwgbW9uaXRvcmluZyBzeXN0ZW1zIGFyZSBub3QgYXZhaWxhYmxlIGluIGEgcGFydGljdWxhciBhcmVhIG9yIHdoZW4gdGhlcmUgaXMgbm90IGVub3VnaCBzcGF0aWFsIGdyYW51bGFyaXR5IHdpdGggY3VycmVudCBtb25pdG9yaW5nIHN5c3RlbXMuIFdlIHdpbGwgdXNlIHNpbWlsYXIgbWV0aG9kcyB0byBwcmVkaWN0IGFubnVhbCBhaXIgcG9sbHV0aW9uIGxldmVscyBzcGF0aWFsbHkgd2l0aGluIHRoZSBVUy4KCgojIyMgTWFpbiBRdWVzdGlvbnMKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb246IDwvdT48L2I+CgoxKSBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPwoKIyMjIwoKIyMjIExlYXJuaW5nIE9iamVjdGl2ZXMgCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgd2FsayB5b3UgdGhyb3VnaCBpbXBvcnRpbmcgZGF0YSBmcm9tIENTViBmaWxlcyBhbmQgcGVyZm9ybWluZyBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdCAoaW4gdGhpcyBjYXNlIGFubnVhbCBmaW5lIHBhcnRpY2xlIGFpciBwb2xsdXRpb24gZXN0aW1hdGVzKS4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIG1vcmUgc3BlY2lmaWNhbGx5IHRoZSBbYHRpZHltb2RlbHNgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdGlkeW1vZGVscy90aWR5bW9kZWxzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBwYWNrYWdlL2Vjb3N5c3RlbSBwcmltYXJpbHkgZGV2ZWxvcGVkIGFuZCBtYWludGFpbmVkIGJ5IFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBhbmQgW0RhdmlzIFZhdWdoYW5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvZGF2aXMtdmF1Z2hhbil7dGFyZ2V0PSJfYmxhbmsifS4gVGhpcyBwYWNrYWdlIGxvYWRzIG1vcmUgbW9kZWxpbmcgcmVsYXRlZCBwYWNrYWdlcyBsaWtlIGByc2FtcGxlYCwgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGB5YXJkc3RpY2tgLCAgYW5kIGBkaWFsc2AuIFdlIHdpbGwgYWxzbyBicmllZmx5IGNvdmVyIHRoZSBgd29ya2Zsb3dzYCBhbmQgYHR1bmVgIHBhY2thZ2VzLiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KCgpgYGB7ciwgb3V0LndpZHRoID0gIjIwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKYGBge3IsIG91dC53aWR0aCA9ICIxMDBweCIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9wYnMudHdpbWcuY29tL21lZGlhL0RrQkZwU3NXNEFJeXlJTi5wbmciKQpgYGAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeShza2ltcikKbGlicmFyeShzdW1tYXJ5dG9vbHMpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoR0dhbGx5KQoKbGlicmFyeSh0aWR5bW9kZWxzKSMgYnJvb20sIGRpYWxzLCBpbmZlciwgcGFyc25pcCwgcHVycnIsIHJlY2lwZXMsIHJzYW1wbGUsIHRpYmJsZSwgeWFyZHN0aWNrCgpsaWJyYXJ5KHdvcmtmbG93cykKbGlicmFyeSh0dW5lKQoKIyBsaWJyYXJ5KHN0cmluZ3IpCiMgbGlicmFyeShwdXJycikKIyBsaWJyYXJ5KHRpYmJsZSkKIyBsaWJyYXJ5KHRpZHlyKQojIGxpYnJhcnkoZ2dwbG90MikKIyBsaWJyYXJ5KGdncHVicikKIyBsaWJyYXJ5KGZvcmNhdHMpCiMgbGlicmFyeShsbWVyVGVzdCkKIyBsaWJyYXJ5KGNhcikKIyBsaWJyYXJ5KGdnaXJhcGgpCiMgbGlicmFyeShnZ2ZvcmNlKQojIGxpYnJhcnkodmlyaWRpcykKIyBsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIENTViBmaWxlIGRhdGEKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byB2aWV3L2FycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgdGhlIGRhdGEgCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhCltzdW1tYXJ5dG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YSBpbiBhIGRpZmZlcmVudCBzdHlsZQpbbWFncml0dHJdKGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byB1c2UgdGhlIGAlPD4lYCBwaXBwaW5nIG9wZXJhdG9yIApbR0dhbGx5XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvR0dhbGx5L0dHYWxseS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgY29ycmVsYXRpb24gcGxvdHMgIApbcnNhbXBsZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL2FydGljbGVzL0Jhc2ljcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHMgYW5kIHRvIHNwbGl0IHRoZSB0cmFpbmluZyBzZXQgZm9yIGNyb3NzLXZhbGlkYXRpb24gIApbcmVjaXBlc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gcHJlLXByb2Nlc3MgZGF0YSBmb3IgbW9kZWxpbmcgaW4gYSB0aWR5IGFuZCByZXByb2R1Y2libGUgd2F5IGFuZCB0byBleHRyYWN0IHByZS1wcm9jZXNzZWQgZGF0YSAobWFqb3IgZnVuY3Rpb25zIGFyZSBgcmVjaXBlKClgICwgYHByZXAoKWAgYW5kIHZhcmlvdXMgdHJhbnNmb3JtYXRpb24gYHN0ZXBfKigpYCBmdW5jdGlvbnMsIGFzIHdlbGwgYXMgYGp1aWNlKClgIC0gZXh0cmFjdHMgZmluYWwgcHJlcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgYW5kIGBiYWtlKClgIC0gYXBwbGllcyByZWNpcGUgc3RlcHMgdG8gdGVzdGluZyBkYXRhKS4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mby4KW3BhcnNuaXBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gICB8IGFuIGludGVyZmFjZSB0byBjcmVhdGUgbW9kZWxzIChtYWpvciBmdW5jdGlvbnMgYXJlICBgZml0KClgLCBgc2V0X2VuZ2luZSgpYCkKW3lhcmRzdGlja10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby95YXJkc3RpY2svKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgbW9kZWxzCiAKCgpbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB3aXRoaW4gdGhlIFBERiBvZiB0aGUgZGF0YQoKW3B1cnJyXShodHRwczovL3B1cnJyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBwZXJmb3JtIGZ1bmN0aW9ucyBvbiBhbGwgY29sdW1ucyBvZiBhIHRpYmJsZQpbdGliYmxlXShodHRwczovL3RpYmJsZS50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgfCB0byBjcmVhdGUgZGF0YSBvYmplY3RzIHRoYXQgd2UgY2FuIG1hbmlwdWxhdGUgd2l0aCBkcGx5ci9zdHJpbmdyL3RpZHlyL3B1cnJyClt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2VwYXJhdGUgZGF0YSB3aXRoaW4gYSBjb2x1bW4gaW50byBtdWx0aXBsZSBjb2x1bW5zCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYWtlIHZpc3VhbGl6YXRpb25zIHdpdGggbXVsdGlwbGUgbGF5ZXJzCltnZ3B1YnJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ3B1YnIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIGVhc2lseSBhZGQgcmVncmVzc2lvbiBsaW5lIGVxdWF0aW9ucyB0byBwbG90cwpbZm9yY2F0c10oaHR0cHM6Ly9mb3JjYXRzLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gY2hhbmdlIGRldGFpbHMgYWJvdXQgZmFjdG9ycyAoY2F0ZWdvcmljYWwgdmFyaWFibGVzKQpbbG1lclRlc3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9sbWVyVGVzdC9sbWVyVGVzdC5wZGYpfCB0byBwZXJmb3JtIGxpbmVhciBtaXhlZCBtb2RlbCB0ZXN0aW5nCltjYXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jYXIvY2FyLnBkZil8IHRvIHBlcmZvcm0gTGV2ZW5lJ3MgVGVzdCBvZiBIb21vZ2VuZWl0eSBvZiBWYXJpYW5jZXMKW2dnaXJhcGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ2lyYXBoL2luZGV4Lmh0bWwpfCB0byBtYWtlIHBsb3RzIGludGVyYWN0aXZlCltnZ2ZvcmNlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dmb3JjZS9nZ2ZvcmNlLnBkZil8IHRvIG1vZGlmeSBmYWNldHMgaW4gcGxvdHMKW3ZpcmlkaXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXJpZGlzL3ZpZ25ldHRlcy9pbnRyby10by12aXJpZGlzLmh0bWwpfCB0byBwbG90IGluIGNvbG9yIHBhbGV0dGUgdGhhdCBpcyBlYXNpbHkgaW50ZXJwcmV0ZWQgYnkgY29sb3JibGluZCBpbmRpdmlkdWFscwpbY293cGxvdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2Nvd3Bsb3QvdmlnbmV0dGVzL2ludHJvZHVjdGlvbi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gYWxsb3cgcGxvdHMgdG8gYmUgY29tYmluZWQKX19fCgoKClRoZSBmaXJzdCB0aW1lIHdlIHVzZSBhIGZ1bmN0aW9uLCB3ZSB3aWxsIHVzZSB0aGUgYDo6YCB0byBpbmRpY2F0ZSB3aGljaCBwYWNrYWdlIHdlIGFyZSB1c2luZy4gVW5sZXNzIHdlIGhhdmUgb3ZlcmxhcHBpbmcgZnVuY3Rpb24gbmFtZXMsIHRoaXMgaXMgbm90IG5lY2Vzc2FyeSwgYnV0IHdlIHdpbGwgaW5jbHVkZSBpdCBoZXJlIHRvIGJlIGluZm9ybWF0aXZlIGFib3V0IHdoZXJlIHRoZSBmdW5jdGlvbnMgd2Ugd2lsbCB1c2UgY29tZSBmcm9tLgoKCiMjIyBDb250ZXh0CgpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXJdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSBpcyBhIHJlcG9ydCByZWxlYXNlZCBldmVyeSB5ZWFyIHRvIGNvbW11bmljYXRlIHRoZSBpbXBhY3Qgb2YgYWlyIHBvbGx1dGlvbiBvbiBwdWJsaWMgaGVhbHRoLiAKClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpciAyMDE5IHJlcG9ydF0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQp3aGljaCB1c2VzIGRhdGEgZnJvbSAyMDE3IHN0YXRlZCB0aGF0OgoKPiBBaXIgcG9sbHV0aW9uIGlzIHRoZSAqKmZpZnRoKiogbGVhZGluZyByaXNrIGZhY3RvciBmb3IgbW9ydGFsaXR5IHdvcmxkd2lkZS4gSXQgaXMgcmVzcG9uc2libGUgZm9yIG1vcmUKZGVhdGhzIHRoYW4gbWFueSBiZXR0ZXIta25vd24gcmlzayBmYWN0b3JzIHN1Y2ggYXMgbWFsbnV0cml0aW9uLCBhbGNvaG9sIHVzZSwgYW5kIHBoeXNpY2FsIGluYWN0aXZpdHkuCkVhY2ggeWVhciwgKiptb3JlKiogcGVvcGxlIGRpZSBmcm9tIGFpciBwb2xsdXRpb27igJNyZWxhdGVkIGRpc2Vhc2UgdGhhbiBmcm9tIHJvYWQgKip0cmFmZmljIGluanVyaWVzKiogb3IgKiptYWxhcmlhKiouCgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly93d3cuaGVhbHRoZWZmZWN0cy5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9Tb0dBLUZpZ3VyZXMtMDEuanBnIj4KPC9wPgoKVGhlIHJlcG9ydCBhbHNvIHN0YXRlZCB0aGF0OgoKPkluIDIwMTcsIGFpciBwb2xsdXRpb24gaXMgZXN0aW1hdGVkIHRvIGhhdmUgY29udHJpYnV0ZWQgdG8gY2xvc2UgdG8gNSBtaWxsaW9uCmRlYXRocyBnbG9iYWxseSDigJQgbmVhcmx5ICoqMSBpbiBldmVyeSAxMCBkZWF0aHMqKi4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3ZGVhdGhzLnBuZyIpKQpgYGAKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9mYWN0X3NoZWV0LnBkZikKClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpciAyMDE4IHJlcG9ydF0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhLTIwMTgtcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgdXNpbmcgZGF0YSBmcm9tIDIwMTYgd2hpY2ggc2VwYXJhdGVkIGRpZmZlcmVudCB0eXBlcyBvZiBhaXIgcG9sbHV0aW9uLCBmb3VuZCB0aGF0ICoqcGFydGljdWxhdGUgcG9sbHV0aW9uIHdhcyBwYXJ0aWN1bGFybHkgYXNzb2NpYXRlZCB3aXRoIG1vcnRhbGl0eSoqLgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIjIwMTdtb3J0YWxpdHkucG5nIikpCmBgYAoKVGhlIDIwMTkgcmVwb3J0IHNob3dzIHRoYXQgdGhlIGhpZ2hlc3QgbGV2ZWxzIG9mIGZpbmUgcGFydGljdWxhdGUgcG9sbHV0aW9uIG9jY3VycyBpbiBBZnJpY2EgYW5kIEFzaWEgYW5kIHRoYXQ6Cgo+IE1vcmUgdGhhbiAqKjkwJSoqIG9mIHBlb3BsZSB3b3JsZHdpZGUgbGl2ZSBpbiBhcmVhcyAqKmV4Y2VlZGluZyoqIHRoZSBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uIChXSE8pICoqR3VpZGVsaW5lKiogZm9yIGhlYWx0aHkgYWlyLiBNb3JlIHRoYW4gaGFsZiBsaXZlIGluIGFyZWFzIHRoYXQgZG8gbm90IGV2ZW4gbWVldCBXSE/igJlzIGxlYXN0LXN0cmluZ2VudCBhaXIgcXVhbGl0eSB0YXJnZXQuCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiUE13b3JsZC5wbmciKSkKYGBgCgpMb29raW5nIGF0IHRoZSBVUyBzcGVjaWZpY2FsbHksIGFpciBwb2xsdXRpb24gbGV2ZWxzIGFyZSBnZW5lcmFsbHkgaW1wcm92aW5nLiBUaGUgVVMgRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKSBhbHNvIHJlbGVhc2VzIGEgcmVwb3J0IGFib3V0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGNhbGxlZCBbKk91ciBOYXRpb24ncyBBaXIqXShodHRwczovL2dpc3B1Yi5lcGEuZ292L2Fpci90cmVuZHNyZXBvcnQvMjAxOS8jaG9tZSl7dGFyZ2V0PSJfYmxhbmsifS4KCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJVUy5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZ2lzcHViLmVwYS5nb3YvYWlyL3RyZW5kc3JlcG9ydC8yMDE5L2RvY3VtZW50YXRpb24vQWlyVHJlbmRzX0ZseWVyLnBkZikKCkhvd2V2ZXIsIGFpciBwb2xsdXRpb24gKipjb250aW51ZXMgdG8gY29udHJpYnV0ZSB0byBoZWFsdGggcmlzayBmb3IgQW1lcmljYW5zKiosIGluIHBhcnRpY3VsYXIgaW4gKipyZWdpb25zIHdpdGggaGlnaGVyIHRoYW4gbmF0aW9uYWwgYXZlcmFnZSByYXRlcyoqIG9mIHBvbGx1dGlvbiB0aGF0IGFjdHVhbGx5IGF0IHRpbWUgZXhjZWVkIHRoZSB3b3JsZCBoZWFsdGggb3JnYW5pemF0aW9uJ3MgcmVjb21tZW5kZWQgbGV2ZWwuIFRodXMgaXQgaXMgbmVjZXNzYXJ5IHRvIG9idGFpbiBoaWdoIHNwYXRpYWwgZ3JhbnVsYXJpdHkgaW4gZXN0aW1hdGVzIG9mIGFpciBwb2xsdXRpb24gaW4gb3JkZXIgdG8gaWRlbnRpZnkgbG9jYXRpb25zIHdoZXJlIHBvcHVsYXRpb25zIGFyZSBleHBlcmllbmNpbmcgaGFybWZ1bCBsZXZlbHMgb2YgZXhwb3N1cmUuCgoKWW91IGNhbiBzZWUgdGhhdCBjdXJyZW50IGFpciBxdWFsaXR5IGNvbmRpdGlvbnMgYXQgdGhpcyBbd2Vic2l0ZV0oaHR0cHM6Ly9hcWljbi5vcmcvY2l0eS91c2EvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB5b3Ugd2lsbCBub3RpY2UgdmFyaWF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgY2l0aWVzLgoKSGVyZSB3ZXJlIHRoZSBjb25kaXRpb25zIGluIFRvcGVrYSBLYW5zYXMgd2hlbiB0aGlzIHdhcyB3cml0dGVuOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIkthbnNhcy5wbmciKSkKYGBgCgpJdCByZXBvcnRzIHBhcnRpY3VsYXRlIHZhbHVlcyB1c2luZyB3aGF0IGlzIGNhbGxlZCB0aGUgW0FpciBRdWFsaXR5IEluZGV4XShodHRwczovL3d3dy5haXJub3cuZ292L2luZGV4LmNmbT9hY3Rpb249YXFpYmFzaWNzLmFxaSl7dGFyZ2V0PSJfYmxhbmsifSBzY2FsZSAoQVFJKSwgdGhpcyBbY2FsY3VsYXRvcl0oaHR0cHM6Ly9haXJub3cuZ292L2luZGV4LmNmbT9hY3Rpb249YWlybm93LmNhbGN1bGF0b3Ipe3RhcmdldD0iX2JsYW5rIn0gaW5kaWNhdGVzIHRoYXQgMTE0IEFRSSBpcyBlcXVpdmFsZW50IHRvIDQwLjcgdWcvbV4zXiBhbmQgaXMgY29uc2lkZXJlZCB1bmhlYWx0aHkgZm9yIHNlbnNpdGl2ZSBpbmRpdmlkdWFscy4gVGh1cyBzb21lIGFyZWFzIHZlcnkgbXVjaCBleGNlZWQgdGhlIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gKFdITykgIGFubnVhbCBleHBvc3VyZSBndWlkZWxpbmUgKDEwIHVnL21eM14pIGF0IGNlcnRhaW4gdGltZXMgYW5kIHRoaXMgbWF5IGFkdmVyc2VseSBhZmZlY3QgdGhlIGhlYWx0aCBvZiBwZW9wbGUgbGl2aW5nIGluIHRoZXNlIGxvY2F0aW9ucy4KCkZ1cnRoZXJtb3JlLCBhZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGhhdmUgYmVlbiBhc3NvY2lhdGVkIHdpdGggcG9wdWxhdGlvbnMgZXhwZXJpZW5jaW5nIGhpZ2hlciBwb2xsdXRpb24gZXhwb3N1cmUgZGVzcGl0ZSB0aGUgbGV2ZWxzIGJlaW5nIGJlbG93IHN1Z2dlc3RlZCBndWlkZWxpbmVzLiBTZWNvbmRseSwgaXQgYXBwZWFycyB0aGF0IHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgcGFydGljdWxhdGUgbWF0ZXIgYW5kIHRoZSBpbmZsdWVuY2Ugb2Ygb3RoZXIgZGVtb2dyYXBoaWMgZmFjdG9ycyBtYXkgbWFrZSBzcGVjaWZpYyBwb3B1bGF0aW9ucyBtb3JlIGF0IHJpc2sgZm9yIGFkdmVyc2UgaGVhbHRoIGVmZmVjdHMgZHVlIHRvIGFpciBwb2xsdXRpb24uIFNlZSB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uZWptLm9yZy9kb2kvZnVsbC8xMC4xMDU2L05FSk1vYTE3MDI3NDcpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgZGV0YWlscy4KClRoZSBtb25pdG9yIGRhdGEgdGhhdCB3ZSB3aWxsIHVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgY29tZXMgZnJvbSBhIHN5c3RlbSBvZiBtb25pdG9ycyBpbiB3aGljaCByb3VnaGx5IDkwJSBhcmUgbG9jYXRlZCB3aXRoaW4gY2l0aWVzLiBUaHVzIHRoZXJlIGlzIGFuICoqZXF1aXR5IGlzc3VlKiogaW4gdGVybXMgb2YgY2FwdHVyaW5nIHRoZSBhaXIgcG9sbHV0aW9uIGxldmVscyBvZiBtb3JlIHJ1cmFsIGFyZWFzLiBUaGVyZWZvcmUsIHRvIGdldCBhIGJldHRlciBzZW5zZSBvZiB0aGUgcG9sbHV0aW9uIGV4cG9zdXJlcyBmb3IgdGhlIGluZGl2aWR1YWxzIGxpdmluZyBpbiB0aGVzZSBhcmVhcywgbWV0aG9kcyBsaWtlIG1hY2hpbmUgbGVhcm5pbmcgY2FuIGJlIHZlcnkgdXNlZnVsIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gbGV2ZWxzIGluICoqYXJlYXMgd2l0aCBsaXR0bGUgdG8gbm8gbW9uaXRvcmluZyoqLgoKSW5kZWVkLCBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgYXJlIGluIGZhY3QgdXNlZCB0byBiZSBhYmxlIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlc2UgbG93IG1vbml0b3JpbmcgYXJlYXMgc28gdGhhdCB3ZSBjYW4gbWFrZSBhIG1hcCBsaWtlIHRoaXMgd2hlcmUgd2UgaGF2ZSBhbm51YWwgZXN0aW1hdGVzIGZvciBhbGwgb2YgdGhlIGNvbnRpZ3VvdXMgVVM6Cgo8cCBhbGlnbj0iY2VudGVyIj4KICA8aW1nIHdpZHRoPSI2MDAiIHNyYz0iaHR0cHM6Ly9hcmMtYW5nbGVyZmlzaC13YXNocG9zdC1wcm9kLXdhc2hwb3N0LnMzLmFtYXpvbmF3cy5jb20vcHVibGljL1NBV09FR0JYTVZHUTdBUzVQWjZVVU9YNkZZLnBuZyI+CjwvcD4KCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3NhPWkmdXJsPWh0dHBzJTNBJTJGJTJGd3d3Lndhc2hpbmd0b25wb3N0LmNvbSUyRmJ1c2luZXNzJTJGMjAxOSUyRjEwJTJGMjMlMkZhaXItcG9sbHV0aW9uLWlzLWdldHRpbmctd29yc2UtZGF0YS1zaG93LW1vcmUtcGVvcGxlLWFyZS1keWluZyUyRiZwc2lnPUFPdlZhdzN2LVpEVEJQbkxQMk1ZdEtmM1VuZGomdXN0PTE1ODU3ODQ0NzkwNjgwMDAmc291cmNlPWltYWdlcyZjZD12ZmUmdmVkPTBDQUlRalJ4cUZ3b1RDUEN5bjlmeHhlZ0NGUUFBQUFBZEFBQUFBQkFkKQoKVGhpcyBpcyB3aGF0IHdlIGFpbSB0byBhY2hpZXZlIGluIHRoaXMgY2FzZSBzdHVkeS4KCiMjIyBMaW1pdGF0aW9ucwoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGlzIGRhdGEgYW5hbHlzaXMgdG8ga2VlcCBpbiBtaW5kOiAKCjEpIFRoZSBkYXRhIGluIG91ciBhbmFseXNpcyBkb2VzIG5vdCBpbmNsdWRlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjb21wb3NpdGlvbiBvZiBwYXJ0aWN1bGF0ZSBtYXRlci4gRGlmZmVyZW50IHR5cGVzIG9mIHBhcnRpY3VsYXRlcyBtYXkgYmUgbW9yZSBiZW5pZ24gb3IgZGVsZXRlcmlvdXMgZm9yIGhlYWx0aCBvdXRjb21lcy4KCjIpIE91dGRvb3IgcG9sbHV0aW9uIGxldmVscyBhcmUgbm90IG5lY2Vzc2FyaWx5IGFuIGluZGljYXRpb24gb2Ygb2YgaW5kaXZpZHVhbCBleHBvc3VyZXMuIFBlb3BsZSBzcGVuZCBkaWZmZXJpbmcgYW1vdW50cyBvZiB0aW1lIGluZG9vcnMgYW5kIG91dGRvb3JzIGFuZCBhcmUgZXhwb3NlZCB0byBkaWZmZXJlbnQgcG9sbHV0aW9uIGxldmVscyBpbmRvb3JzLiBQZW9wbGUgYXJlIG5vdyBkZXZlbG9waW5nIHBlcnNvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyB0byB0cmFjayBhaXIgcG9sbHV0aW9uIGxldmVscyBvbiB0aGUgcGVyc29uYWwgbGV2ZWwuCgpPdXIgYW5hbHlzaXMgd2lsbCB1c2UgYW5udWFsIG1lYW4gZXN0aW1hdGVzLCBob3dldmVyIHBvbGx1dGlvbiBsZXZlbHMgY2FuIHZhcnkgZ3JlYXRseSBieSBzZWFzb24sIGRheSBhbmQgZXZlbiBob3VyLiBUaGVyZSBhcmUgZGF0YSBzb3VyY2VzIHRoYXQgaGF2ZSBmaW5lciBsZXZlbHMgb2YgdGVtcG9yYWwgZGF0YSwgaG93ZXZlciB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBsb25nIHRlcm0gZXhwb3N1cmVzLCBhcyB0aGVzZSBhcHBlYXIgdG8gYmUgdGhlIG1vc3QgaW5mbHVlbnRpYWwgZm9yIGhlYWx0aCBvdXRjb21lcywgc28gd2UgY2hvc2UgdG8gdXNlIGFubnVhbCBsZXZlbCBkYXRhLiAKCgojIyBXaGF0IGFyZSB0aGUgZGF0YT8KCkluIE1hY2hpbmUgTGVhcm5pbmcgZm9yIHByZWRpY3Rpb24sIHRoZXJlIGFyZSB0d28gbWFpbiB0eXBlcyBvZiB2YXJpYWJsZXM6CgoxKSBPdXRjb21lIHZhcmlhYmxlCjIpIFByZWRpY3RvciB2YXJpYWJsZXMKClRoZSAqKm91dGNvbWUgdmFyaWFibGUqKiBpcyB3aGF0IGFyZSB0cnlpbmcgdG8gKipwcmVkaWN0KiouIEluIGJ1aWxkaW5nIG91ciBtb2RlbCB3ZSBhY3R1YWxseSBoYXZlIHRoZSBvdXRjb21lIHZhcmlhYmxlIGRhdGEsIGJ1dCB3ZSB3YW50IHRvIHNlZSBob3cgd2VsbCBvdXIgcHJlZGljdG9yIHZhcmlhYmxlcyBjYW4gZXhwbGFpbiB0aGUgdmFyaWF0aW9uIGluIG91ciBvdXRjb21lIGRhdGEuIFRoaXMgZ2l2ZXMgdXMgYSBzZW5zZSBvZiBob3cgd2VsbCB3ZSBjYW4gdXNlIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUgZGF0YSB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlIGxldmVscyB3aGVuIHdlIGluIGZhY3QgZG8gbm90IGhhdmUgZGF0YSBhYm91dCB0aGUgb3V0Y29tZS4KCkFzIGEgc2ltcGxlciBleGFtcGxlLCBpbWFnaW5lIHRoYXQgd2UgaGF2ZSBkYXRhIGFib3V0IHRoZSBzYWxlcyBhbmQgY2hhcmFjdGVyaXN0aWNzIG9mIGNhcnMgZnJvbSBsYXN0IHllYXIgYW5kIHdlIHdhbnQgdG8gcHJlZGljdCB3aGljaCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIFdlIGRvIG5vdCBoYXZlIHRoZSBzYWxlcyBkYXRhIHlldCBmb3IgdGhpcyB5ZWFyLCBidXQgd2UgZG8ga25vdyB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIG91ciBjYXJzIGZvciB0aGlzIHllYXIuIFdlIGNhbiB1c2UgYSBtb2RlbCBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIHRoYXQgZXhwbGFpbmVkIHNhbGVzIGxhc3QgeWVhciB0byBlc3RpbWF0ZSB3aGF0IGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gSW4gdGhpcyBjYXNlLCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBpcyB0aGUgc2FsZSBwZXJmb3JtYW5jZSBvZiB0aGUgY2Fycywgd2hpbGUgdGhlIGRpZmZlcmVudCBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGNhcnMgbWFrZSB1cCBvdXIgcHJlZGljdG9yIG9yIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4KCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCBldmFsdWF0ZSBhaXIgcG9sbHV0aW9uIG1vbml0b3IgZGF0YSBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdGVyIChQTX4yLjV+KSBpbiB0aGUgY29udGlndW91cyBVUyBmcm9tIDIwMDgsIGFzIHdlbGwgYXMgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHJvYWQgZGVuc2l0eSwgdXJiYW5pemF0aW9uIGxldmVscywgYW5kIE5BU0Egc2F0ZWxsaXRlIGRhdGEgdG8gZGV2ZWxvcCBtb2RlbHMgdG8gcHJlZGljdCBsb2NhbGl6ZWQgYWlyIHBvbGx1dGlvbiBsZXZlbHMuIAoKVGhlIG1vbml0b3IgZGF0YSB3aWxsIGJlIG91ciAqKm91dGNvbWUgdmFyaWFibGUqKi4gIFdlIHdhbnQgdG8gZGV0ZXJtaW5lIGlmIHdlIGNhbiAqKnByZWRpY3QqKiBhaXIgcG9sbHV0aW9uIGxldmVscyBiYXNlZCBvbiBvdGhlciB0eXBlcyBvZiBkYXRhLCBsaWtlIHJvYWQgZGVuc2l0eSBhbmQgcG9wdWxhdGlvbiBkZW5zaXR5IHRvIHNlZSBpZiB3ZSBjYW4gdXNlIHRoZXNlIGRhdGEgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGluIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBubyBtb25pdG9ycy4gCgoKIyMjIE91ciBvdXRjb21lIHZhcmlhYmxlCgpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCBiZSB1c2luZyBjb21lcyBmcm9tICoqW2dyYXZpbWV0cmljIG1vbml0b3JzXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0qKiBvcGVyYXRlZCBieSB0aGUgVVMgW0VuaXZvcm5tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSldKGh0dHBzOi8vd3d3LmVwYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LiBUaGVzZSBtb25pdG9ycyB1c2UgYSBmaWx0cmF0aW9uIHN5c3RlbSB0byBzcGVjaWZpY2FsbHkgY2FwdHVyZSBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlci4gVGhlIHdlaWdodCBvZiB0aGlzIG1hdHRlciBpcyBtYW51YWxseSBtZWFzdXJlZCBkYWlseSBvciB3ZWVrbHkuIFNlZSBbaGVyZV0oaHR0cHM6Ly93d3czLmVwYS5nb3YvdHRuYW10aTEvZmlsZXMvYW1iaWVudC9wbTI1L3NwZWMvUlRJR3Jhdk1hc3NTT1BGSU5BTC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gZm9yIHRoZSBFUEEgc3RhbmRhcmQgb3BlcmF0aW5nIHByb2NlZHVyZSBmb3IgUE0gZ3JhdmltZXRyaWMgYW5hbHlzaXMgaW4gMjAwOC4KCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxNTBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImZpbHRlci5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV0oaHR0cHM6Ly9wdWJsaWNsYWIub3JnL3dpa2kvZmlsdGVyLXBtKV0KCkhlcmUgaXMgYW4gaW1hZ2Ugb2Ygd2hhdCB0aGUgZ3JhdmltZXRyaWMgbW9uaXRvcnMgbG9vayBsaWtlOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxMDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIm1vbml0b3IucG5nIikpCmBgYAoKCkdyYXZpbWV0cmljIGFuYWx5c2lzIGlzIGFsc28gdXNlZCBmb3IgW2VtaXNzaW9uIHRlc3RpbmddKGh0dHBzOi8vd3d3Lm10LmNvbS91cy9lbi9ob21lL2FwcGxpY2F0aW9ucy9MYWJvcmF0b3J5X3dlaWdoaW5nL2VtaXNzaW9ucy10ZXN0aW5nLXBhcnRpY3VsYXRlLW1hdHRlci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LiBUaGUgc2FtZSBpZGVhIGFwcGxpZXM6IGEgZnJlc2ggZmlsdGVyIGlzIGFwcGxpZWQgYW5kIHRoZSBkZXNpcmVkIGFtb3VudCBvZiB0aW1lIHBhc3NlcywgdGhlbiB0aGUgZmlsdGVyIGlzIHJlbW92ZWQgYW5kIHdlaWdoZWQuIAoKVGhlcmUgYXJlIFtvdGhlciBtb25pdG9yaW5nIHN5c3RlbXNdKGh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vZW4vYWJvdXQtdXMvbmV3c3Jvb20vc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZXMvcGFydGljdWxhdGUtbWF0dGVyLXNlbnNpbmctZm9yLWFpci1xdWFsaXR5LW1lYXN1cmVtZW50cy8pe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBjYW4gcHJvdmlkZSBob3VybHkgbWVhc3VyZW1lbnRzLCBidXQgd2Ugd2lsbCBub3QgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZXNlIG1vbml0b3JzIGluIG91ciBhbmFseXNpcy4gR3JhdmltZXRyaWMgYW5hbHlzaXMgaXMgY29uc2lkZXJlZCB0byBiZSBhbW9uZyB0aGUgbW9zdCBhY2N1cmF0ZSBtZXRob2RzLgoKSW4gb3VyIGNzdiwgdGhlICoqdmFsdWUqKiBjb2x1bW4gaW5kaWNhdGVzIHRoZSBQTX4yLjV+IG1vbml0b3IgYXZlcmFnZSBmb3IgMjAwOCBpbiBtYXNzIG9mIGZpbmUgcGFydGljbGVzL3ZvbHVtZSBvZiBhaXIgZm9yIDg3NiBncmF2aW1ldHJpYyBtb25pdG9ycy4gVGhlIHVuaXRzIGFyZSBtaWNybyBncmFtcyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdGVyIChQTSkgdGhhdCBpcyBsZXNzIHRoYW4gMi41IG1pY3JvbWV0ZXJzIGluIGRpYW1ldGVyIHBlciBjdWJpYyBtZXRlciBvZiBhaXIgLSBtYXNzIGNvbmNlbnRyYXRpb24gKHVnL21eM14pLiAgUmVjYWxsIHRoZSB0aGUgV0hPIGV4cG9zdXJlICBndWlkZWxpbmUgaXMgPCAxMCB1Zy9tXjNeIG9uIGF2ZXJhZ2UgYW5udWFsbHkgZm9yIFBNfjIuNX4uCgojIyMgT3VyIHByZWRpY3RvciB2YXJpYWJsZXMKClRoZXJlIGFyZSA0OCBwcmVkaWN0b3IgdmFyaWFibGVzIHdpdGggdmFsdWVzIGZvciBlYWNoIG9mIHRoZSA4NzYgbW9uaXRvcnMgaW5jbHVkZWQgaW4gb3VyIG91dGNvbWUgdmFyaWFibGUuIFRoZSBkYXRhIGNvbWVzIGZyb20gdGhlIFVTIFtFbml2b3JubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpXShodHRwczovL3d3dy5lcGEuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlIFtOYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24gKE5BU0EpXShodHRwczovL3d3dy5uYXNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIHRoZSBVUyBbQ2Vuc3VzXShodHRwczovL3d3dy5jZW5zdXMuZ292L2Fib3V0L3doYXQvY2Vuc3VzLWF0LWEtZ2xhbmNlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIGFuZCB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3MgKE5DSFMpXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvYWJvdXQvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKVmFyaWFibGUgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQoqKmlkKiogIHwgTW9uaXRvciBudW1iZXIgIDxicj4gLS0gdGhlIGNvdW50eSBudW1iZXIgaXMgaW5kaWNhdGVkIGJlZm9yZSB0aGUgZGVjaW1hbCA8YnI+IC0tIHRoZSBtb25pdG9yIG51bWJlciBpcyBpbmRpY2F0ZWQgYWZ0ZXIgdGhlIGRlY2ltYWwgPGJyPiAgKipFeGFtcGxlKio6IDEwNzMuMDAyMyAgaXMgSmVmZmVyc29uIGNvdW50eSAoMTA3MykgYW5kIC4wMDIzIG9uZSBvZiA4IG1vbml0b3JzIAoqKmZpcHMqKiB8IEZlZGVyYWwgaW5mb3JtYXRpb24gcHJvY2Vzc2luZyBzdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDUgZGlnaXQgaWQgY29kZSBmb3IgY291bnRpZXMgKHplcm8gaXMgb2Z0ZW4gdGhlIGZpcnN0IHZhbHVlIGFuZCBzb21ldGltZXMgaXMgbm90IHNob3duKSA8YnI+IC0tIHRoZSBmaXJzdCAyIG51bWJlcnMgaW5kaWNhdGUgdGhlIHN0YXRlIDxicj4gLS0gdGhlIGxhc3QgdGhyZWUgbnVtYmVycyBpbmRpY2F0ZSB0aGUgY291bnR5IDxicj4gICoqRXhhbXBsZSoqOiBBbGFiYW1hJ3Mgc3RhdGUgY29kZSBpcyAwMSBiZWNhdXNlIGl0IGlzIGZpcnN0IGFscGhhYmV0aWNhbGx5IDxicj4gKG5vdGU6IEFsYXNrYSBhbmQgSGF3YWlpIGFyZSBub3QgaW5jbHVkZWQgYmVjYXVzZSB0aGV5IGFyZSBub3QgcGFydCBvZiB0aGUgY29udGlndW91cyBVUykgIAoqKkxhdCoqIHwgTGF0aXR1ZGUgb2YgdGhlIG1vbml0b3IgaW4gZGVncmVlcyAgCioqTG9uKiogfCBMb25naXR1ZGUgb2YgdGhlIG1vbml0b3IgaW4gZGVncmVlcyAgCioqc3RhdGUqKiB8IFN0YXRlIHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQKKipjb3VudHkqKiB8IENvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqY2l0eSoqIHwgQ2l0eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqQ01BUSoqICB8IEVzdGltYXRlZCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBmcm9tIGEgY29tcHV0YXRpb25hbCBtb2RlbCBjYWxsZWQgWyoqQ29tbXVuaXR5IE11bHRpc2NhbGUgQWlyIFF1YWxpdHkgKENNQVEpKipdKGh0dHBzOi8vd3d3LmVwYS5nb3YvY21hcSl7dGFyZ2V0PSJfYmxhbmsifSA8YnI+IC0tICBBIG1vbml0b3Jpbmcgc3lzdGVtIHRoYXQgc2ltdWxhdGVzIHRoZSBwaHlzaWNzIG9mIHRoZSBhdG1vc3BoZXJlIHVzaW5nIGNoZW1pc3RyeSBhbmQgd2VhdGhlciBkYXRhIHRvIHByZWRpY3QgdGhlIGFpciBwb2xsdXRpb24gPGJyPiAtLSAqKipEb2VzIG5vdCB1c2UgYW55IG9mIHRoZSBQTX4yLjV+IGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YS4qKiogKFRoZXJlIGlzIGEgdmVyc2lvbiB0aGF0IGRvZXMgdXNlIHRoZSBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEsIGJ1dCBub3QgdGhpcyBvbmUhKSA8YnI+IC0tIERhdGEgZnJvbSB0aGUgRVBBCioqemN0YSoqIHwgW1ppcCBDb2RlIFRhYnVsYXRpb24gQXJlYV0oaHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3BkZnMvZWR1Y2F0aW9uL2Jyb2NodXJlcy9aQ1RBcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIFBvc3RhbCBaaXAgY29kZXMgYXJlIGNvbnZlcnRlZCBpbnRvICJnZW5lcmFsaXplZCBhcmVhbCByZXByZXNlbnRhdGlvbnMiIHRoYXQgYXJlIG5vbi1vdmVybGFwcGluZyAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKip6Y3RhX2FyZWEqKiB8IExhbmQgYXJlYSBvZiB0aGUgemlwIGNvZGUgYXJlYSBpbiBtZXRlcnMgc3F1YXJlZCAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKip6Y3RhX3BvcCoqIHwgUG9wdWxhdGlvbiBpbiB0aGUgemlwIGNvZGUgYXJlYSAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKippbXBfYTUwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciA8YnI+IC0tIEltcGVydmlvdXMgc3VyZmFjZSBhcmUgcm9hZHMsIGNvbmNyZXRlLCBwYXJraW5nIGxvdHMsIGJ1aWxkaW5ncyA8YnI+IC0tIFRoaXMgaXMgYSBtZWFzdXJlIG9mIGRldmVsb3BtZW50IAoqKmltcF9hMTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yCioqaW1wX2E1MDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgIAoqKmltcF9hMTAwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgICAKKippbXBfYTE1MDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAKKipjb3VudHlfYXJlYSoqIHwgTGFuZCBhcmVhIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgaW4gbWV0ZXJzIHNxdWFyZWQgIAoqKmNvdW50eV9wb3AqKiB8IFBvcHVsYXRpb24gb2YgdGhlIGNvdW50eSBvZiB0aGUgbW9uaXRvciAgCioqTG9nX2Rpc3RfdG9fcHJpc2VjKiogfCBMb2cgKE5hdHVyYWwgbG9nKSBkaXN0YW5jZSB0byBhIHByaW1hcnkgb3Igc2Vjb25kYXJ5IHJvYWQgZnJvbSB0aGUgbW9uaXRvciA8YnI+IC0tIEhpZ2h3YXkgb3IgbWFqb3Igcm9hZCAgCioqbG9nX3ByaV9sZW5ndGhfNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzEwMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzE1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzI1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzUwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF81MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzE1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMjUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAKKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAKKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMjUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAKKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTAwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzE1MDAwKip8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzI1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKnBvcGRlbnNfY291bnR5KiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgdGhlIGNvdW50eSkKKipwb3BkZW5zX3pjdGEqKiB8IFBvcHVsYXRpb24gZGVuc2l0eSAobnVtYmVyIG9mIHBlb3BsZSBwZXIga2lsb21ldGVyIHNxdWFyZWQgYXJlYSBvZiB6Y3RhKQoqKm5vaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0ICoqZG8gbm90IGhhdmUgYSBoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzCioqc29tZWhzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgKipzb21lIGhpZ2ggc2Nob29sIGVkdWNhdGlvbioqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMKKipocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgYSAqKmhpZ2ggc2Nob29sIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgIAoqKnNvbWVjb2xsZWdlKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyAqKnNvbWUgY29sbGVnZSBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKmFzc29jaWF0ZSoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgYW4gKiphc3NvY2lhdGUgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKipiYWNoZWxvcioqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipiYWNoZWxvcidzIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqZ3JhZCoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipncmFkdWF0ZSBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKnBvdioqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIGlzIHRoYXQgbGl2ZWQgaW4gWyoqcG92ZXJ0eSoqXShodHRwczovL2FzcGUuaGhzLmdvdi8yMDA4LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMpIGluIDIwMDggLSBvciB3b3VsZCBpdCBoYXZlIGJlZW4gMjAwNyBndWlkZWxpbmVzPz9odHRwczovL2FzcGUuaGhzLmdvdi8yMDA3LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMgPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAgCioqaHNfb3JsZXNzKiogfCAgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipoaWdoIHNjaG9vbCBkZWdyZWUgb3IgbGVzcyoqIChzdW0gb2Ygbm9ocywgc29tZWhzLCBhbmQgaHMpICAKKip1cmMyMDEzKiogfCBbMjAxMyBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTY2LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+ICAtLSBEYXRhIGZyb20gdGhlIE5hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIAoqKnVyYzIwMDYqKiB8IFsyMDA2IFVyYmFuLXJ1cmFsIGNsYXNzaWZpY2F0aW9uXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvZGF0YS9zZXJpZXMvc3JfMDIvc3IwMl8xNTQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDYgY2F0ZWdvcnkgdmFyaWFibGUgLSAxIGlzIHRvdGFsbHkgdXJiYW4gNiBpcyBjb21wbGV0ZWx5IHJ1cmFsIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgQ2VudGVyIGZvciBIZWFsdGggU3RhdGlzdGljc10oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgCioqYW9kKiogfCBBZXJvc29sIE9wdGljYWwgRGVwdGggbWVhc3VyZW1lbnQgZnJvbSBhIE5BU0Egc2F0ZWxsaXRlIDxicj4gLS0gYmFzZWQgb24gdGhlIGRlZnJhY3Rpb24gb2YgYSBsYXNlciA8YnI+IC0tIHVzZWQgYXMgYSBwcm94eSBvZiBwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gPGJyPiAtLSB1bml0LWxlc3MgLSBoaWdoZXIgdmFsdWUgaW5kaWNhdGVzIG1vcmUgcG9sbHV0aW9uIDxicj4gLS0gRGF0YSBmcm9tIE5BU0EgIAoKTWFueSBvZiB0aGVzZSBwcmVkaWN0b3IgdmFyaWFibGVzIGhhdmUgdG8gZG8gd2l0aCB0aGUgY2lyY3VsYXIgYXJlYSBhcm91bmQgdGhlIG1vbml0b3IgY2FsbGVkIHRoZSAiYnVmZmVyIi4gVGhlc2UgYXJlIGlsbHVzdHJhdGVkIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMHB4Iix9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJyZWdyZXNzaW9uLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8xNTI5MjkwNildCgoKCiMjIERhdGEgSW1wb3J0CgpXZSBoYXZlIG9uZSBDU1YgZmlsZSB0aGF0IGNvbnRhaW5zIGJvdGggb3VyIHNpbmdsZSAqKm91dGNvbWUgdmFyaWFibGUqKiBhbmQgYWxsIG9mIG91ciAqKnByZWRpY3RvciB2YXJpYWJsZXMqKi4KCkxldCdzIGltcG9ydCBvdXIgZGF0YSBpbnRvIFIgbm93IHNvIHRoYXQgd2UgY2FuIGV4cGxvcmUgdGhlIGRhdGEgZnVydGhlci4gV2Ugd2lsbCBjYWxsIG91ciBkYXRhIG9iamVjdCBgcG1gIGZvciBwYXJ0aWN1bGF0ZSBtYXR0ZXIuCgpgYGB7cn0KcG0gPC1yZWFkcjo6cmVhZF9jc3YoaGVyZSgiZG9jcyIsICJwbTI1X2RhdGEuY3N2IikpCmBgYAoKIyMgRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nCgpUaGUgZmlyc3Qgc3RlcCBpbiBwZXJmb3JtaW5nIGEgbWFjaGluZSBsZWFybmluZyBhbmFseXNpcyBpcyB0byBleHBsb3JlIHRoZSBkYXRhIHRvIGJldHRlciB1bmRlcnN0YW5kIHRoZSB2YXJpYWJsZXMgIGluY2x1ZGVkIGluIHRoZSBkYXRhLCBhcyB3ZSBtYXkgbGVhcm4gYWJvdXQgaW1wb3J0YW50IGRldGFpbHMgYWJvdXQgdGhlIGRhdGEgdGhhdCB3ZSBzaG91bGQga2VlcCBpbiBtaW5kIGFzIHdlIHRyeSB0byBwcmVkaWN0IG91ciBvdXRjb21lIHZhcmlhYmxlLgoKRmlyc3QgbGV0J3MganVzdCBnZXQgYSBnZW5lcmFsIHNlbnNlIG9mIG91ciBkYXRhLiBXZSBjYW4gZG8gdGhhdCB1c2luZyB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSAoaXQgaXMgYWxzbyBpbiB0aGUgYHRpYmJsZWAgcGFja2FnZSkuCgpXZSB3aWxsIGFsc28gdXNlIHRoZSBgJT4lYCBwaXBlIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGRlZmluZSB0aGUgaW5wdXQgZm9yIGxhdGVyIHNlcXVlbnRpYWwgc3RlcHMuIFRoaXMgd2lsbCBtYWtlIG1vcmUgc2Vuc2Ugd2hlbiB3ZSBoYXZlIG11bHRpcGxlIHNlcXVlbnRpYWwgc3RlcHMgdXNpbmcgdGhlIHNhbWUgZGF0YSBvYmplY3QuIFRvIHVzZSB0aGUgcGlwZSBub3RhdGlvbiB3ZSBuZWVkIHRvIGluc3RhbGwgYW5kIGxvYWQgZHBseXIgYXMgd2VsbC4KCkZvciBleGFtcGxlIGhlcmUgd2Ugd2lsbCBmaXJzdCBncmFiIHRoZSBgcG1gIGRhdGEgb2JqZWN0LCB0aGVuIHdlIHVzZSB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24gb24gaXQgYmFzZWQgb24gdGhlIHBpcGUgbm90YXRpb24uCgoKYGBge3J9CnBtICU+JQogIGRwbHlyOjpnbGltcHNlKCkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDg3NiBtb25pdG9ycyBhbmQgdGhhdCB3ZSBoYXZlIDUwIHRvdGFsIHZhcmlhYmxlcyAtIG9uZSBvZiB3aGljaCBpcyB0aGUgb3V0Y29tZS4gSW4gdGhpcyBjYXNlIG91ciBvdXRjb21lIHZhcmlhYmxlIGlzIGNhbGxlZCBgdmFsdWVgLiAKCk5vdGljZSB0aGF0IHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB0aGF0IHdlIHdvdWxkIHRoaW5rIG9mIGFzIGZhY3RvcnMgKGNhdGVnb3JpY2FsKSBhcmUgY3VycmVudGx5IG9mIGNsYXNzIGRvdWJsZSBhcyBpbmRpY2F0ZWQgYnkgdGhlIGA8ZGJsPmAganVzdCB0byB0aGUgcmlnaHQgb2YgdGhlIGNvbHVtbiBuYW1lcy92YXJpYWJsZSBuYW1lcyBpbiB0aGUgYGdsaW1wc2UoKWAgb3V0cHV0LiBGb3IgZXhhbXBsZSB0aGUgbW9uaXRvciBJRCAoaWQpLCB0aGUgRmVkZXJhbCBJbmZvcm1hdGlvbiBQcm9jZXNzaW5nIFN0YW5kYXJkIG51bWJlciBmb3IgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCAoZmlwcyksIGFzIHdlbGwgYXMgdGhlIHpjdGEKCkxldCdzIGNvbnZlcnQgdGhlc2UgdmFyaWFibGVzIGludG8gZmFjdG9ycy4gV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBtdXRhdGVfYXQoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSBhbmQgdGhlIGBhcy5mYWN0b3IoKWAgYmFzZSBmdW5jdGlvbi4gCgpJbiB0aGlzIGNhc2Ugd2UgYXJlIGFsc28gdXNpbmcgdGhlIG1hZ3JpdHRyIGFzc2lnbm1lbnQgcGlwZSBvciBkb3VibGUgcGlwZSB0aGF0IGxvb2tzIGxpa2UgdGhpcyBgJTw+JWAgb2YgdGhlIGBtYWdyaXR0cmAgcGFja2FnZS4gVGhpcyBhbGxvd3MgdXMgdXNlIHRoZSBgcG1gIGRhdGEgYXMgaW5wdXQgYnV0IGFsc28gcmVhc3NpZ24gdGhlIG91dHB1dCB0byB0aGUgc2FtZSBkYXRhIG9iamVjdCBuYW1lLgoKYGBge3J9CnBtICU8PiUKICBkcGx5cjo6bXV0YXRlX2F0KHZhcnMoaWQsIGZpcHMsIHpjdGEpLCBhcy5mYWN0b3IpIAoKZ2xpbXBzZShwbSkKYGBgCgpHcmVhdCEgTm93IHdlIGNhbiBzZWUgdGhhdCB0aGVzZSB2YXJpYWJsZXMgYXJlIG5vdyBmYWN0b3JzIGFzIGluZGljYXRlZCBieSBgPGZjdD5gIGFmdGVyIHRoZSB2YXJpYWJsZSBuYW1lLgoKVGhlIGBza2ltKClgIGZ1bmN0aW9uIG9mIHRoZSBgc2tpbXJgIHBhY2thZ2UgaXMgYWxzbyByZWFsbHkgaGVscGZ1bCBmb3IgZ2V0dGluZyBhIGdlbmVyYWwgc2Vuc2Ugb2YgeW91ciBkYXRhLgoKYGBge3J9CnNraW0ocG0pCmBgYAoKTm90aWNlIGhvdyB0aGVyZSBpcyBhIGNvbHVtbiBjYWxsZWQgYG5fbWlzc2luZ2AgYWJvdXQgdGhlIG51bWJlciBvZiB2YWx1ZXMgdGhhdCBhcmUgbWlzc2luZy4gSXQgbG9va3MgbGlrZSBvdXIgZGF0YSBpcyB2ZXJ5IGNvbXBsZXRlIGFuZCB3ZSBkbyBub3QgaGF2ZSBhbnkgbWlzc2luZyBkYXRhLiBUaGlzIGlzIGFsc28gaW5kaWNhdGVkIGJ5IHRoZSBgY29tcGxldGVfcmF0ZWAgdmFyaWFibGUsIHdoaWNoIHNob3dzIHRoZSByYXRpbyBvZiBjb21wbGV0ZW5lc3MsIGluIG91ciBjYXNlIGFsbCB2YXJpYWJsZXMgaGF2ZSBhIHZhbHVlIG9mIDEgaW5kaWNhdGluZyB0aGV5IGFyZSBmdWxseSBjb21wbGV0ZS4KClRoZSBgbl91bnFpdWVgIGNvbHVtbiBzaG93cyB1cyB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB2YWx1ZXMgZm9yIGVhY2ggb2Ygb3VyIGNvbHVtbnMuIFdlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgNDkgc3RhdGVzIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhLCBhbmQgd2Uga25vdyB0aGF0IHRoZSBkYXRhIHNob3VsZCBiZSBvZiB0aGUgY29udGlndW91cyBzdGF0ZXMuIExldCdzIHRha2UgYSBsb29rIHRvIHNlZSB3aGljaCBzdGF0ZXMgYXJlIGluY2x1ZGVkOgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpwbSAlPiUgCiAgZGlzdGluY3Qoc3RhdGUpICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAojIyMjCgpMb29rcyBsaWtlICJEaXN0cmljdCBvZiBDb2x1bWJpYSIgaXMgYmVpbmcgaW5jbHVkZWQgYXMgYSBzdGF0ZS4gV2UgY2FuIHNlZSB0aGF0IGluZGVlZCBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBkYXRhLgoKSGVyZSBpcyBhbm90aGVyIG1ldGhvZCBvZiBsb29raW5nIGF0IHRoZSBkYXRhIHVzaW5nIHRoZSBgZGZTdW1tYXJ5KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3VtbWFyeXRvb2xzYHBhY2thZ2UuIFdlIG5lZWQgdG8gY29weSBhbmQgcGFzdGUgdGhlIG91dHB1dCBpbnRvIHRoZSBybWFya2Rvd24uCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpkZlN1bW1hcnkocG0sIHBsYWluLmFzY2lpID0gRkFMU0UsIHN0eWxlID0gImdyaWQiLCAKICAgICAgICAgIGdyYXBoLm1hZ25pZiA9IDAuNDUsICB0bXAuaW1nLmRpciA9ICJ0bXAiKQpgYGAKCioqRGltZW5zaW9uczoqKiA4NzYgeCA1MCAgCioqRHVwbGljYXRlczoqKiAwICAKCistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgTm8gfCBWYXJpYWJsZSAgICAgICAgICAgICAgICAgICAgIHwgU3RhdHMgLyBWYWx1ZXMgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEZyZXFzICglIG9mIFZhbGlkKSAgfCBHcmFwaCAgICAgICAgICAgICAgIHwgVmFsaWQgIHwgTWlzc2luZyB8Cis9PT09Kz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0rPT09PT09PT09PT09PT09PT09PT09Kz09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PSs9PT09PT09PT0rCnwgMSAgfCBpZFwgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMDMuMDAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDEwMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDEwMjcuMDAwMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEwMzMuMTAwMlwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDEwNDkuMTAwM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDEwNTUuMDAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDEwNjkuMDAwM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDEwNzMuMDAyM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDEwNzMuMTAwNVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDEwNzMuMTAwOVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAxMDczLjEwMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA4NjYgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg2NiAoOTguOSUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMiAgfCB2YWx1ZVwgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuOCAoMi42KVwgICAgICAgICAgICAgICAgICB8IDg3NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMyA8IDExLjIgPCAyMy4yXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjEgKDAuMikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMyAgfCBmaXBzXCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMDNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDEwMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDEwMjdcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEwMzNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDEwNDlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDEwNTVcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDEwNjlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDEwNzNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDggKCAwLjklKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDEwODlcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDEwOTdcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAxMTAxXCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA1NTkgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg1OCAoOTguMCUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNCAgfCBsYXRcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzguNSAoNC42KVwgICAgICAgICAgICAgICAgICB8IDg3NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMjUuNSA8IDM5LjMgPCA0OC40XCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2LjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNSAgfCBsb25cICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogLTkxLjcgKDE1KVwgICAgICAgICAgICAgICAgICB8IDg3NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLTEyNC4yIDwgLTg3LjUgPCAtNjhcICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOC41ICgtMC4yKSAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNiAgfCBzdGF0ZVwgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIENhbGlmb3JuaWFcICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg1ICggOS43JSlcICAgICAgICAgfCAhW10odG1wL2RzMDEwNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIE9oaW9cICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDQ0ICggNS4wJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIElsbGlub2lzXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDM4ICggNC4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIEluZGlhbmFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDM2ICggNC4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIE5vcnRoIENhcm9saW5hXCAgICAgICAgICAgICAgICAgICAgICB8IDM1ICggNC4wJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIFBlbm5zeWx2YW5pYVwgICAgICAgICAgICAgICAgICAgICAgICB8IDMyICggMy43JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIE1pY2hpZ2FuXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMwICggMy40JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIEZsb3JpZGFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI5ICggMy4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIEdlb3JnaWFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI4ICggMy4yJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBUZXhhc1wgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDI3ICggMy4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyAzOSBvdGhlcnMgXSAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDQ5MiAoNTYuMiUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNyAgfCBjb3VudHlcICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIEplZmZlcnNvblwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDE4ICggMi4xJSlcICAgICAgICAgfCAhW10odG1wL2RzMDEwNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIENvb2tcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEyICggMS40JSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIEhhbWlsdG9uXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDExICggMS4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIExha2VcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDExICggMS4zJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIExvcyBBbmdlbGVzXCAgICAgICAgICAgICAgICAgICAgICAgICB8IDEwICggMS4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIFdheW5lXCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEwICggMS4xJSlcICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIFdhc2hpbmd0b25cICAgICAgICAgICAgICAgICAgICAgICAgICB8IDkgKCAxLjAlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIEN1eWFob2dhXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIEphY2tzb25cICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBNYWRpc29uXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcgKCAwLjglKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA0NjEgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDc3NCAoODguNCUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgOCAgfCBjaXR5XCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIE5vdCBpbiBhIGNpdHlcICAgICAgICAgICAgICAgICAgICAgICB8IDEwMyAoMTEuOCUpXCAgICAgICAgfCAhW10odG1wL2RzMDEwOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbY2hhcmFjdGVyXSAgICAgICAgICAgICAgICAgIHwgMlwuIE5ldyBZb3JrXCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDkgKCAxLjAlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIENsZXZlbGFuZFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgKCAwLjclKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIEJhbHRpbW9yZVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIENoaWNhZ29cICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIERldHJvaXRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIE1pbHdhdWtlZVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIE5ldyBIYXZlblwgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIFBoaWxhZGVscGhpYVwgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiBTcHJpbmdmaWVsZFwgICAgICAgICAgICAgICAgICAgICAgICB8IDUgKCAwLjYlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA1OTcgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDcyMyAoODIuNSUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgOSAgfCBDTUFRXCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogOC40ICgzKVwgICAgICAgICAgICAgICAgICAgICB8IDYwMSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEwOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMS42IDwgOC42IDwgMjMuMVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjcgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTAgfCB6Y3RhXCAgICAgICAgICAgICAgICAgICAgICAgIHwgMVwuIDEwMjJcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAhW10odG1wL2RzMDExMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbZmFjdG9yXSAgICAgICAgICAgICAgICAgICAgIHwgMlwuIDExMDNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgM1wuIDEyMDFcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNFwuIDE2MDhcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDIgKCAwLjIlKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNVwuIDE4MzJcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNlwuIDE4NDBcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgN1wuIDE4NjNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOFwuIDE5MDRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOVwuIDIxMTNcICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTBcLiAyMTE5XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDEgKCAwLjElKVwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgWyA4MzIgb3RoZXJzIF0gICAgICAgICAgICAgICAgICAgICAgICAgICB8IDg2NCAoOTguNiUpICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTEgfCB6Y3RhX2FyZWFcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTgzMTczNDgxLjkgKDU0MjU5ODg3OC41KVwgICB8IDg0MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTU0NTkgPCAzNzY1MzU2MC41IDwgODE2NDgyMDYyNVwgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNDU4MzY5MDYuNSAoMykgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTIgfCB6Y3RhX3BvcFwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQyMjcuNiAoMTc3NzIuMilcICAgICAgICAgICB8IDgzNyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDIyMDE0IDwgOTUzOTdcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyNTIwNy44ICgwLjcpICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTMgfCBpbXBfYTUwMFwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQuNyAoMTkuMylcICAgICAgICAgICAgICAgICB8IDgxNiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDI1LjEgPCA2OS42XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzNi41ICgwLjgpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTQgfCBpbXBfYTEwMDBcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjQuMyAoMTgpXCAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDI0LjUgPCA2Ny41XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzMy4zICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTUgfCBpbXBfYTUwMDBcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTkuOSAoMTQuNylcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgMTkuMSA8IDc0LjZcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyMy4zICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTYgfCBpbXBfYTEwMDAwXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTUuOCAoMTMuOClcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgMTIuNCA8IDcyLjFcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOS42ICgwLjkpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTcgfCBpbXBfYTE1MDAwXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTMuNCAoMTMuMSlcICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4xIDwgOS43IDwgNzEuMVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNy4zICgxKSAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTggfCBjb3VudHlfYXJlYVwgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzc2ODcwMTk5Mi4xICg2MjEyODI5NTUzLjYpXCB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMzM3MDM1MTIgPCAxNjkwODI2NTY2LjUgPCA1MTk0NzIyOTUwOVwgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNzYxNjU1OTExLjUgKDEuNikgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMTkgfCBjb3VudHlfcG9wXCAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNjg3Mjk4LjQgKDEyOTM0ODguNylcICAgICAgICB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDExOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNzgzIDwgMjgwNzMwLjUgPCA5ODE4NjA1XCAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2NDIyMTEgKDEuOSkgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjAgfCBsb2dfZGlzdF90b19wcmlzZWNcICAgICAgICAgIHwgTWVhbiAoc2QpIDogNi4yICgxLjQpXCAgICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgLTEuNSA8IDYuNCA8IDEwLjVcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjcgKDAuMikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjEgfCBsb2dfcHJpX2xlbmd0aF81MDAwXCAgICAgICAgIHwgTWVhbiAoc2QpIDogOS44ICgxLjEpXCAgICAgICAgICAgICAgICAgICB8IDU4NiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOC41IDwgMTAuMSA8IDEyXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjIgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjIgfCBsb2dfcHJpX2xlbmd0aF8xMDAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuOSAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDY4NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS4yIDwgMTEuMiA8IDEzXCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjMgfCBsb2dfcHJpX2xlbmd0aF8xNTAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTEuNSAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDcyNiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS42IDwgMTEuNyA8IDEzLjZcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjUgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjQgfCBsb2dfcHJpX2xlbmd0aF8yNTAwMFwgICAgICAgIHwgTWVhbiAoc2QpIDogMTIuMiAoMS4xKVwgICAgICAgICAgICAgICAgICB8IDc4NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTAuMSA8IDEyLjUgPCAxNC40XCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjQgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjUgfCBsb2dfcHJpc2VjX2xlbmd0aF81MDBcICAgICAgIHwgTWVhbiAoc2QpIDogNyAoMSlcICAgICAgICAgICAgICAgICAgICAgICB8IDM4MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNi4yIDwgNi4yIDwgOS40XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjYgfCBsb2dfcHJpc2VjX2xlbmd0aF8xMDAwXCAgICAgIHwgTWVhbiAoc2QpIDogOC42ICgwLjgpXCAgICAgICAgICAgICAgICAgICB8IDU5MSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNy42IDwgOC43IDwgMTAuNVwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxLjYgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjcgfCBsb2dfcHJpc2VjX2xlbmd0aF81MDAwXCAgICAgIHwgTWVhbiAoc2QpIDogMTEuMyAoMC44KVwgICAgICAgICAgICAgICAgICB8IDg1MiBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOC41IDwgMTEuNCA8IDEyLjhcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAwLjkgKDAuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjggfCBsb2dfcHJpc2VjX2xlbmd0aF8xMDAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTIuNCAoMC43KVwgICAgICAgICAgICAgICAgICB8IDg2NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS4yIDwgMTIuNSA8IDEzLjhcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMjkgfCBsb2dfcHJpc2VjX2xlbmd0aF8xNTAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTMgKDAuNylcICAgICAgICAgICAgICAgICAgICB8IDg2OSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEyOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOS42IDwgMTMuMSA8IDE0LjRcICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzAgfCBsb2dfcHJpc2VjX2xlbmd0aF8yNTAwMFwgICAgIHwgTWVhbiAoc2QpIDogMTMuOCAoMC43KVwgICAgICAgICAgICAgICAgICB8IDg3MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMTAuMSA8IDEzLjkgPCAxNS4yXCAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxICgwLjEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzEgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDBcIHwgTWVhbiAoc2QpIDogNCAoMi40KVwgICAgICAgICAgICAgICAgICAgICB8IDgyOCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQuMyA8IDkuMVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjUgKDAuNikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzIgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTUwMDBcIHwgTWVhbiAoc2QpIDogNC43ICgyLjIpXCAgICAgICAgICAgICAgICAgICB8IDg1NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUgPCA5LjRcICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjkgKDAuNSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzMgfCBsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMjUwMDBcIHwgTWVhbiAoc2QpIDogNS43ICgyLjEpXCAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzMy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuOSA8IDkuN1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjYgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzQgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTAwMDBcIHwgTWVhbiAoc2QpIDogNC4zICgyLjMpXCAgICAgICAgICAgICAgICAgICB8IDgyOSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQuNiA8IDkuM1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjQgKDAuNSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzUgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTUwMDBcIHwgTWVhbiAoc2QpIDogNS4xICgyLjIpXCAgICAgICAgICAgICAgICAgICB8IDg1NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuNCA8IDkuN1wgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjggKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzYgfCBsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMjUwMDBcIHwgTWVhbiAoc2QpIDogNi4xICgyKVwgICAgICAgICAgICAgICAgICAgICB8IDg2MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYuNCA8IDkuOVwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyLjQgKDAuMykgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzcgfCBwb3BkZW5zX2NvdW50eVwgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNTUxLjggKDE3MTEuNSlcICAgICAgICAgICAgICB8IDU2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzNy5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMC4zIDwgMTU2LjcgPCAyNjgyMS45XCAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA0NzAgKDMuMSkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzggfCBwb3BkZW5zX3pjdGFcICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTI3OS43ICgyNzU3LjUpXCAgICAgICAgICAgICB8IDg0MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzOC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYxMC4zIDwgMzA0MTguOFwgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMjgxLjQgKDIuMikgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgMzkgfCBub2hzXCAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNyAoNy4yKVwgICAgICAgICAgICAgICAgICAgICB8IDIxNSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDEzOS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDUuMSA8IDEwMFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA2LjEgKDEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDAgfCBzb21laHNcICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTAuMiAoNi4yKVwgICAgICAgICAgICAgICAgICB8IDIzMCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0MC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDkuNCA8IDcyLjJcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA4ICgwLjYpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDEgfCBoc1wgICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMzAuMyAoMTEuNClcICAgICAgICAgICAgICAgICB8IDM0NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0MS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDMwLjggPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMi4zICgwLjQpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDIgfCBzb21lY29sbGVnZVwgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMjEuNiAoOC42KVwgICAgICAgICAgICAgICAgICB8IDI0MCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Mi5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDIxLjMgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA3LjIgKDAuNCkgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDMgfCBhc3NvY2lhdGVcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNy4xICg0KVwgICAgICAgICAgICAgICAgICAgICB8IDE1NyBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0My5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDcuMSA8IDcxLjRcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAzLjkgKDAuNikgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDQgfCBiYWNoZWxvclwgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTQuOSAoOS43KVwgICAgICAgICAgICAgICAgICB8IDMwMSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0NC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDEyLjkgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxMC40ICgwLjcpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDUgfCBncmFkXCAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogOC45ICg4LjYpXCAgICAgICAgICAgICAgICAgICB8IDI0NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0NS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDYuNyA8IDEwMFwgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiA3LjEgKDEpICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDYgfCBwb3ZcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMTUgKDExLjMpXCAgICAgICAgICAgICAgICAgICB8IDM0NSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Ni5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDEyLjEgPCA2NS45XCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxNC43ICgwLjgpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDcgfCBoc19vcmxlc3NcICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNDcuNSAoMTYuOClcICAgICAgICAgICAgICAgICB8IDQ2NCBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE0Ny5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCA8IDQ4LjcgPCAxMDBcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyMS4yICgwLjQpICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDggfCB1cmMyMDEzXCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMi45ICgxLjUpXCAgICAgICAgICAgICAgICAgICB8IDEgOiAyMDMgKDIzLjIlKVwgICAgfCAhW10odG1wL2RzMDE0OC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8IDIgOiAxNjMgKDE4LjYlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMSA8IDMgPCA2XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMgOiAyMjggKDI2LjAlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjUpICAgICAgICAgICAgICAgICAgICAgICB8IDQgOiAxMjMgKDE0LjAlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgOiAxMDEgKDExLjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgOiAgNTggKCA2LjYlKSAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNDkgfCB1cmMyMDA2XCAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogMyAoMS41KVwgICAgICAgICAgICAgICAgICAgICB8IDEgOiAxOTUgKDIyLjMlKVwgICAgfCAhW10odG1wL2RzMDE0OS5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8IDIgOiAxNjIgKDE4LjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMSA8IDMgPCA2XCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDMgOiAyMjEgKDI1LjIlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAyICgwLjUpICAgICAgICAgICAgICAgICAgICAgICB8IDQgOiAxMjcgKDE0LjUlKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDUgOiAxMTUgKDEzLjElKVwgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDYgOiAgNTYgKCA2LjQlKSAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCnwgNTAgfCBhb2RcICAgICAgICAgICAgICAgICAgICAgICAgIHwgTWVhbiAoc2QpIDogNDMuNyAoMTkuNilcICAgICAgICAgICAgICAgICB8IDU4MSBkaXN0aW5jdCB2YWx1ZXMgfCAhW10odG1wL2RzMDE1MC5wbmcpIHwgODc2XCAgIHwgMFwgICAgICB8CnwgICAgfCBbbnVtZXJpY10gICAgICAgICAgICAgICAgICAgIHwgbWluIDwgbWVkIDwgbWF4OlwgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgKDEwMCUpIHwgKDAlKSAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNSA8IDQwLjIgPCAxNDNcICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CnwgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgSVFSIChDVikgOiAxOCAoMC40KSAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwgICAgICAgICB8CistLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLSstLS0tLS0tLS0rCgoKV2UgY2FuIHNlZSB0aGF0IGZvciBtYW55IHZhcmlhYmxlcyB0aGVyZSBhcmUgbWFueSBsb3cgdmFsdWVzIGFzIHRoZSBkaXN0cmlidXRpb24gc2hvd3MgdHdvIHBlYWtzLCBvbmUgbmVhciB6ZXJvIGFuZCBhbm90aGVyIHdpdGggYSBoaWdoZXIgdmFsdWUuIFRoaXMgaXMgdHJ1ZSBmb3IgdGhlIGltcCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGRldmVsb3BtZW50KSwgdGhlIG5laSB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGVtaXNzaW9uIHNvdXJjZXMpIGFuZCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIHJhbmdlIG9mIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBpcyB2ZXJ5IGxhcmdlLCBpbiBwYXJ0aWN1bGFyIHRoZSBhcmVhIGFuZCBwb3B1bGF0aW9uIHJlbGF0ZWQgdmFyaWFibGVzLgoKCkluIHByZWRpY3Rpb24gYW5hbHlzZXMsIGl0IGlzIGFsc28gdXNlZnVsIHRvIGV2YWx1YXRlIGlmIGFueSBvZiB0aGUgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkLgoKSW50dWl0aXZlbHkgd2UgY2FuIGV4cGVjdCBzb21lIG9mIG91ciB2YXJpYWJsZXMgdG8gYmUgY29ycmVsYXRlZC4KCldlIGV4cGVjdCB0aGUgZGV2ZWxvcG1lbnQgdmFyaWFibGVzIChpbXApIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLCB3ZSBleHBlY3QgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgdG8gYmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIsIHdlIGV4cGVjdCB0aGUgZW1pc3Npb24gdmFyaWFibGVzIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLCBhbmQgd2UgYWxzbyBleHBlY3QgdGhlc2UgdmFyaWFibGVzIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlciBhbmQgbGlrZWx5IGNvcnJlbGF0ZWQgd2l0aCBwb3B1bGF0aW9uIGRlbnNpdHkuIFdlIGNhbiBnZXQgYSBuaWNlIHZpc3VhbGl6YXRpb24gb2YgY29ycmVsYXRpb24gdXNpbmcgdGhlIGBnZ2NvcnIoKWAgZnVuY3Rpb24gYW5kIHRoZSBgZ2dwYWlycygpYCBmdW5jdGlvbiBvZiB0aGUgYEdHYWxseWAgcGFja2FnZS4gdG8gc2VsZWN0IG91ciB2YXJpYWJsZXMgb2YgaW50ZXJlc3Qgd2UgY2FuIHVzZSB0aGUgYHNlbGVjdCgpYCBmdW5jdGlvbiB3aXRoIHRoZSBgY29udGFpbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZS4gCgpGaXJzdCBsZXQncyBsb29rIGF0IHRoZSBpbXAvZGV2ZWxvcG1lbnQgdmFyaWFibGVzLiAKYGBge3IsIG91dC53aWR0aCA9ICI0MDBweCJ9CnNlbGVjdChwbSwgY29udGFpbnMoImltcCIpKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgbGFiZWwgPSBUUlVFKQoKc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQogIGdncGFpcnMoKQogIApgYGAKCkluZGVlZCwgd2UgY2FuIHNlZSB0aGF0IGltcF9hMTAwMCBhbmQgaW1wX2E1MDAgYXJlIHBlcmZlY3RseSBjb3JyZWxhdGVkLCBhcyB3ZWxsIGFzIGltcF9hMTAwMDAsIGltcF9hMTUwMDAuCgoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSByb2FkIGRlbnNpdHkgZGF0YToKCmBgYHtyLCBmaWcud2VpZ2h0PTEyfQpzZWxlY3QocG0sIGNvbnRhaW5zKCJwcmkiKSkgJT4lCiAgZ2djb3JyKHBhbGV0dGUgPSAiUmRCdSIsICBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKCnNlbGVjdChwbSwgY29udGFpbnMoInByaSIpKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgd2hpbGUgc29tZSBvZiB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlciAob3IgYW50aS1jb3JyZWxhdGVkKSwgdGhlcmUgYXJyIHNvbWUgdmFyaWFibGVzIHRoYXQgYXJlIGxlc3MgY29ycmVsYXRlZCB3aXRoIG9uZSBhbm90aGVyLgoKRmluYWxseSBsZXQncyBsb29rIGF0IHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMuCgpgYGB7cn0Kc2VsZWN0KHBtLCBjb250YWlucygibmVpIikpICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lCiAgZ2dwYWlycygpCmBgYAoKV2Ugd291bGQgYWxzbyBleHBlY3QgdGhlIHBvcHVsYXRpb24gZGVuc2l0eSBkYXRhIG1pZ2h0IGNvcnJlbGF0ZSB3aXRoIHNvbWUgb2YgdGhlc2UgdmFyaWFibGVzLiBMZXQncyB0YWtlIGEgbG9vay4KCmBgYHtyfQpwbSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgcG9wZGVuc19jb3VudHksIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKcG0gJT4lCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgY291bnR5X3BvcCkgJT4lCiAgZ2dwYWlycygpCmBgYAoKCkludGVyZXN0aW5nLCBzbyB0aGVzZSB2YXJpYWJsZXMgZG9uJ3QgYXBwZWFyIHRvIGJlIGhpZ2hseSBjb3JyZWxhdGVkLCB0aGVyZWZvcmUgd2UgbWlnaHQgbmVlZCB2YXJpYWJsZXMgZnJvbSBlYWNoIG9mIHRoZSBjYXRlZ29yaWVzIHRvIHByZWRpY3Qgb3VyIG1vbml0b3IgUE1+Mi41fiBwb2xsdXRpb24gdmFsdWVzLgoKV2Ugc2VlbSB0byBoYXZlIHNvbWUgcHJldHR5IGV4dHJlbWUgcG9wdWxhdGlvbiB2YWx1ZXMgdGhvdWdoLCBzbyBsZXQncyBzZWUgd2hhdCBoYXBwZW5zIHdoZW4gd2UgdGFrZSB0aGUgbG9nIHZhbHVlLgoKYGBge3J9CnBtICU+JQogIG11dGF0ZShsb2dfcG9wZGVuc19jb3VudHk9IGxvZyhwb3BkZW5zX2NvdW50eSkpICU+JQpzZWxlY3QobG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwLCBsb2dfcG9wZGVuc19jb3VudHksIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKcG0gJT4lCiAgbXV0YXRlKGxvZ19wb3BkZW5zX2NvdW50eT0gbG9nKHBvcGRlbnNfY291bnR5KSkgJT4lCiAgbXV0YXRlKGxvZ19wb3BfY291bnR5ID0gbG9nKGNvdW50eV9wb3ApKSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgbG9nX3BvcGRlbnNfY291bnR5LCBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgbG9nX3BvcF9jb3VudHkpICU+JQogIGdncGFpcnMoKQpgYGAKCkluZGVlZCB0aGlzIGluY3JlYXNlZCB0aGUgY29ycmVsYXRpb24sIGJ1dCB2YXJpYWJsZXMgZnJvbSBlYWNoIG9mIHRoZXNlIGNhdGVnb3JpZXMgbWF5IHN0aWxsIHByb3ZlIHRvIGJlIHVzZWZ1bCBmb3IgcHJlZGljdGlvbi4KCgojIyBEYXRhIEFuYWx5c2lzCgpOb3cgdGhhdCB3ZSBoYXZlIGEgc2Vuc2Ugb2Ygd2hhdCBvdXIgZGF0YSBpcyBsaWtlIHdlIGNhbiBnZXQgc3RhcnRlZCB3aXRoIGRhdGEgYW5hbHlzaXMuCgoKIyMjIFRoZSB0aWR5bW9kZWxzIGVjb3N5c3RlbQoKVG8gcGVyZm9ybSBvdXIgYW5hbHlzaXMgd2Ugd2lsbCBiZSB1c2luZyB0aGUgYHRpZHltb2RlbHNgIHN1aXRlIG9mIHBhY2thZ2VzLiBZb3UgbWF5IGJlIGZhbWlsaWFyIHdpdGggdGhlIG9sZGVyIHBhY2thZ2VzIGBjYXJldGAgb3IgYG1scmAgd2hpY2ggYXJlIGFsc28gZm9yIG1hY2hpbmUgbGVhcm5pbmcgYW5kIG1vZGVsaW5nIGJ1dCBhcmUgbm90IGEgcGFydCBvZiB0aGUgYHRpZHl2ZXJzZWAuIFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBkZXNjcmliZXMgYHRpZHltb2RlbHNgIGxpa2UgdGhpczoKCj4gIk90aGVyIHBhY2thZ2VzLCBzdWNoIGFzIGNhcmV0IGFuZCBtbHIsIGhlbHAgdG8gc29sdmUgdGhlIFIgbW9kZWwgQVBJIGlzc3VlLiBUaGVzZSBwYWNrYWdlcyBkbyBhIGxvdCBvZiBvdGhlciB0aGluZ3MgdG9vOiBwcmVwcm9jZXNzaW5nLCBtb2RlbCB0dW5pbmcsIHJlc2FtcGxpbmcsIGZlYXR1cmUgc2VsZWN0aW9uLCBlbnNlbWJsaW5nLCBhbmQgc28gb24uIEluIHRoZSB0aWR5dmVyc2UsIHdlIHN0cml2ZSB0byBtYWtlIG91ciBwYWNrYWdlcyBtb2R1bGFyIGFuZCBwYXJzbmlwIGlzIGRlc2lnbmVkIG9ubHkgdG8gc29sdmUgdGhlIGludGVyZmFjZSBpc3N1ZS4gSXQgaXMgbm90IGRlc2lnbmVkIHRvIGJlIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgY2FyZXQuClRoZSB0aWR5bW9kZWxzIHBhY2thZ2UgY29sbGVjdGlvbiwgd2hpY2ggaW5jbHVkZXMgcGFyc25pcCwgaGFzIG90aGVyIHBhY2thZ2VzIGZvciBtYW55IG9mIHRoZXNlIHRhc2tzLCBhbmQgdGhleSBhcmUgZGVzaWduZWQgdG8gd29yayB0b2dldGhlci4gV2UgYXJlIHdvcmtpbmcgdG93YXJkcyBoaWdoZXItbGV2ZWwgQVBJcyB0aGF0IGNhbiByZXBsaWNhdGUgYW5kIGV4dGVuZCB3aGF0IHRoZSBjdXJyZW50IG1vZGVsIHBhY2thZ2VzIGNhbiBkby4iCgoKIyMjIFRoZSBtYWpvciBiZW5lZml0cyBvZiB0aWR5bW9kZWxzCjEpIHN0YW5kYXJkaXplZCB3b3JrZmxvdy9mb3JtYXQvbm90YXRpb24gYWNyb3NzIGRpZmZlcmVudCB0eXBlcyBvZiBhbGdvcml0aG1zCjIpIGNhbiBlYXNpbHkgbW9kaWZ5IHByZXByb2Nlc3NpbmcsIGFsZ29yaXRobSBjaG9pY2UsIGFuZCBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nIG1ha2luZyBvcHRpbWl6YXRpb24gZWFzeQoKCiMjIyBUaGUgbWFjaGluZSBsZWFybmluZyBwcm9jZXNzCgoKIyMjIFRoZSB0aWR5bW9kZWxzIGVjb3N5c3RlbSAtIGFuIG92ZXJ2aWV3CgpUaGVyZSBhcmUgbWFueSBwYWNrYWdlcyBpbiB0aGUgdGlkeW1vZGVscyBlY29zeXN0ZW0gd2hpY2ggYXNzaXN0IHdpdGggdGhlIHZhcmlvdXMgc3RlcHMgb2YgdGhlIG1hY2hpbmUgbGVhcm5pbmcgcHJvY2VzczoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwic2ltcGxldGlkeW1vZGVscy5wbmciKSkKYGBgCgoKVGhpcyBpcyB0aGUgb3ZlcmFsbCBwcm9jZXNzOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWNoaW5lTGVhcm5pbmcucG5nIikpCmBgYAoKVGhlcmUgYXJlIHR3byBkaXN0aW5jdCBnb2FscyBvZiBzdXBlcnZpc2VkIG1hY2hpbmUgbGVhcm5pbmc6ICAKCjEpIFByZWRpY3Rpb24gIAoyKSBDbGFzc2lmaWNhdGlvbiAgCgpXZSB3aWxsIGJlIHBlcmZvcm1pbmcgYSBwcmVkaWN0aW9uIGFuYWx5c2lzICh3aGljaCBpcyBhbHNvIHJlZmVyZWQgdG8gYXMgcmVncmVzc2lvbiksIHdoaWNoIGFpbXMgdG8gcHJlZGljdCAqKmNvbnRpbnVvdXMgb3V0Y29tZSoqIHZhcmlhYmxlcyBnaXZlbiBhIG51bWJlciBvZiBwcmVkaWN0b3JzL2V4cGxhbmF0b3J5IHZhcmlhYmxlcy9mZWF0dXJlcy9wYXJhbWV0ZXJzLCBhcyB3ZSBoYXZlIGFscmVhZHkgZGVzY3JpYmVkLgoKQ2xhc3NpZmljYXRpb24gb24gdGhlIG90aGVyIGhhbmQgYWltcyB0byBkaXNjZXJuIG9yIHByZWRpY3QgZ3JvdXAgaWRlbnRpdHkgZm9yIGEgKipjYXRlZ29yaWNhbCBvdXRjb21lKiogYmFzZWQgb24gYSBudW1iZXIgb2YgcHJlZGljdG9ycy9leHBsYW5hdG9yeSB2YXJpYWJsZXMvZmVhdHVyZXMvcGFyYW1ldGVycy4KClRoZSBvdmVyYWxsIHByb2Nlc3MgaXMgdGhlIHNhbWUgaW4gZWl0aGVyIGNhc2UuIAoKIyMjIFNwbGl0dGluZyB0aGUgRGF0YQoKVGhlIGZpcnN0IHN0ZXAgYWZ0ZXIgZGF0YSBleHBsb3JhdGlvbiBpbiBtYWNoaW5lIGxlYXJuaW5nIGFuYWx5c2lzIGlzIHRvIFtzcGxpdCB0aGUgZGF0YV0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXZhbGlkYXRpb24tYW5kLXRlc3Qtc2V0cy03MmNiNDBjYmE5ZTcpe3RhcmdldD0iX2JsYW5rIn0gaW50byAqKnRyYWluaW5nKiogYW5kICoqdGVzdGluZyoqIGRhdGFzZXRzLiAKClRoZSB0cmFpbmluZyBkYXRhc2V0IHdpbGwgYmUgdXNlZCB0byBidWlsZCBhbmQgdHVuZSBvdXIgbW9kZWwuIFRoaXMgaXMgdGhlIGRhdGEgdGhhdCB0aGUgbW9kZWwgImxlYXJucyIgb24uCgpUaGUgdGVzdGluZyBzZXQgd2lsbCBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgaW4gYSBtb3JlIGdlbmVyYWxpemFibGUgd2F5LiBXaGF0IGRvIHdlIG1lYW4gYnkgImdlbmVyYWxpemFibGUiPwoKUmVtZW1iZXIgdGhhdCBvdXIgbWFpbiBnb2FsIGlzIHRvIHVzZSBvdXIgbW9kZWwgdG8gYmUgYWJsZSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGluIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBubyBncmF2aW1ldHJpYyBtb25pdG9ycy4gVGhlcmVmb3JlLCBpZiBvdXIgbW9kZWwgaXMgc3VwZXIgZ29vZCBhdCBwcmVkaWN0aW5nIGFpciBwb2xsdXRpb24gd2l0aCB0aGUgZGF0YSB0aGF0IHdlIHVzZSB0byBidWlsZCBpdCwgaXQgbWlnaHQgbm90IGRvIHRoZSBiZXN0IGpvYiBmb3IgdGhlIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBmZXcgdG8gbm8gbW9uaXRvcnMuIFRoaXMgd291bGQgY2F1c2UgdXMgdG8gaGF2ZSByZWFsbHkgZ29vZCBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCB3ZSBtaWdodCBhc3N1bWUgdGhhdCB3ZSB3ZXJlIGdvaW5nIHRvIGRvIGEgZ29vZCBqb2IgZXN0aW1hdGluZyBhaXIgcG9sbHV0aW9uIGFueSB0aW1lIHdlIHVzZSBvdXIgbW9kZWwsIGJ1dCBpbiBmYWN0IHRoaXMgd291bGQgbGlrZWx5IG5vdCBiZSB0aGUgY2FzZS4gVGhpcyBzaXR1YXRpb24gaXMgd2hhdCB3ZSBjYWxsICoqW292ZXJmaXR0aW5nXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdGVzdC1zcGxpdC1hbmQtY3Jvc3MtdmFsaWRhdGlvbi1pbi1weXRob24tODBiNjFiZWNhNGI2KXt0YXJnZXQ9Il9ibGFuayJ9ICoqLgoKT3ZlcmZpdHRpbmcgaGFwcGVucyB3aGVuIHdlIGVuZCB1cCBtb2RlbGluZyBub3Qgb25seSB0aGUgbWFqb3IgcmVsYXRpb25zaGlwcyBpbiBvdXIgZGF0YSBidXQgYWxzbyB0aGUgbm9pc2Ugd2l0aGluIG91ciBkYXRhLiAKCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMTEwLzEqdEJFclhZVnZUdzJqU1VZSzd0aFUyQS5wbmciKQpgYGAKCiMjIyMjIFtbc291cmNlXShodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTExMC8xKnRCRXJYWVZ2VHcyalNVWUs3dGhVMkEucG5nKV0KCklmIHdlIGdldCBmYWlybHkgZ29vZCBwcmVkaWN0aW9uIHdpdGggb3VyIHRlc3Rpbmcgc2V0IHRoZW4gd2Ugd2lsbCBrbm93IHRoYXQgb3VyIG1vZGVsIGNhbiBiZSBhcHBsaWVkIHRvIG90aGVyIGRhdGEgYW5kIHdpbGwgcGVyZm9ybSBmYWlybHkgd2VsbC4gV2Ugd2lsbCBkaXNjdXNzIHRoaXMgbW9yZSBsYXRlci4KCldlIHdpbGwgbm90IHRvdWNoIHRoZSB0ZXN0aW5nIHNldCB1bnRpbCB3ZSBoYXZlIGNvbXBsZXRlZCBvcHRpbWl6aW5nIG91ciBtb2RlbCB3aXRoIHRoZSB0cmFpbmluZyBzZXQuIFRoaXMgd2lsbCBhbGxvdyB1cyB0byBoYXZlIGEgbGVzcyBiaWFzZWQgZXZhbHVhdGlvbiBvZiBob3cgd2VsbCBvdXIgbW9kZWwgY2FuIGRvIHdpdGggb3RoZXIgZGF0YSBiZXNpZGVzIHRoZSBkYXRhIHVzZWQgaW4gdGhlIHRyYWluaW5nIHNldCB0byBidWlsZCB0aGUgbW9kZWwuIElkZWFsbHkgeW91IHdvdWxkIGFsc28gd2FudCBhIGNvbXBsZXRlbHkgaW5kZXBlbmRlbnQgZGF0YXNldCB0byBmdXJ0aGVyIHRlc3QgdGhlIHBlcmZvcm1hbmNlIG9mIHlvdXIgbW9kZWwuCgpbSGVyZV0oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLXRlc3QtdmFsaWRhdGlvbi1kYXRhc2V0cy8pe3RhcmdldD0iX2JsYW5rIn0gaXMgYSBncmVhdCBkZXNjcmlwdGlvbiBvZiB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0ZXN0aW5nIGFuZCB0cmFpbmluZyBkYXRhc2V0cy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwic3BsaXQucG5nIikpCmBgYApXZSB3aWxsIHVzZSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gcGVyZm9ybSB0aGlzIHN0ZXAuCgpUaGVgaW5pdGlhbF9zcGxpdCgpYCBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gc3BlY2lmeSBob3cgd2Ugd2FudCB0byBzcGxpdCBvdXIgZGF0YS4gVHlwaWNhbGx5IGRhdGEgaXMgc3BsaXQgaW50byAzLzQgZm9yIHRyYWluaW5nIGFuZCAxLzQgZm9yIHRlc3RpbmcuVGhpcyBpcyB0aGUgZGVmYXVsdCBwcm9wb3J0aW9uIGFuZCBkb2VzIG5vdCBuZWVkIHRvIGJlIHNwZWNpZmllZC4gSG93ZXZlciB5b3UgY2FuIGNoYW5nZSB0aGUgcHJvcG9ydGlvbiB1c2luZyB0aGUgYHByb3BgIGFyZ3VtZW50LCB3aGljaCB3ZSB3aWxsIGRvIHRoYXQgaGVyZSBmb3IgaWxsdXN0cmF0aXZlIHB1cnBvc2VzLiBZb3UgY2FuIGFsc28gc3BlY2lmeSBhIHZhcmlhYmxlIHRvIHN0cmF0aWZ5IGJ5IHdpdGggdGhlIGBzdHJhdGFgIGFyZ3VtZW50LiBUaGlzIGlzIHVzZWZ1bCBpZiB5b3UgaGF2ZSBpbWJhbGFuY2VkIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgeW91IHdvdWxkIGxpa2UgdG8gaW50ZW50aW9uYWxseSBtYWtlIHN1cmUgdGhhdCB0aGVyZSBhcmUgc2ltaWxhciBudW1iZXIgb2Ygc2FtcGxlcyBvZiB0aGUgcmFyZXIgY2F0ZWdvcmllcyBpbiBib3RoIHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzLiBPdGhlcndpc2UgdGhlIHNwbGl0IGlzIHBlcmZvcm1lZCByYW5kb21seS4gCgo+IFRoZSBzdHJhdGEgYXJndW1lbnQgY2F1c2VzIHRoZSByYW5kb20gc2FtcGxpbmcgdG8gYmUgY29uZHVjdGVkIHdpdGhpbiB0aGUgc3RyYXRpZmljYXRpb24gdmFyaWFibGUuIFRoZSBjYW4gaGVscCBlbnN1cmUgdGhhdCB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIHRoZSB0cmFpbmluZyBkYXRhIGlzIGVxdWl2YWxlbnQgdG8gdGhlIHByb3BvcnRpb25zIGluIHRoZSBvcmlnaW5hbCBkYXRhIHNldC4KCkluIHRoZSBjYXNlIHdpdGggb3VyIGRhdGFzZXQsIHBlcmhhcHMgd2Ugd291bGQgbGlrZSBvdXIgdHJhaW5pbmcgc2V0IHRvIGhhdmUgc2ltaWxhciBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBmcm9tIGVhY2ggb2YgdGhlIHN0YXRlcyBhcyBpbiB0aGUgaW5pdGlhbCBkYXRhLiBUaGlzIG1pZ2h0IGJlIHVzZWZ1bCBpZiB3ZSB3YW50IG91ciBtb2RlbCB0byBiZSBnZW5lcmFsaXphYmxlIGFjcm9zcyBhbGwgb2YgdGhlIHN0YXRlcy4KCldlIGNhbiBzZWUgdGhhdCBpbmRlZWQgdGhlcmUgYXJlIGRpZmZlcmVudCBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBpbiBlYWNoIHN0YXRlIGJ5IHVzaW5nIHRoZSBgY291bnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcHlyYCBwYWNrYWdlLiAKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKY291bnQocG0sIHN0YXRlKSAlPiUKICBwcmludChuID0gMWUzKQpgYGAKIyMjIwoKSWYgb3VyIGRhdGFzZXQgd2VyZSBsYXJnZSBlbm91Z2ggaXQgbWlnaHQgYmUgbmljZSB0aGVuIHRvIHN0cmF0aWZ5IGJ5IHN0YXRlLCBidXQgb3VyIGRhdGEgaXMgdW5mb3J0dW5hdGVseSBub3QgbGFyZ2UgZW5vdWdoLiBXZSB3aWxsIHNob3cgaG93IG9uZSB3b3VsZCBkbyB0aGlzIHRob3VnaCBmb3IgaWxsdXN0cmF0aXZlIHB1cnBvc2VzLiBUaGlzIG9wdGlvbiBpcyBvZnRlbiBtb3JlIGltcG9ydGFudCBmb3IgY2xhc3NpZmljYXRpb24gYXBwbGljYXRpb25zIG9mIG1hY2hpbmUgbGVhcm5pbmcgdGhhbiBpdCBpcyBmb3IgcHJlZGljdGlvbi4KClNpbmNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHksIGl0IGlzIGEgZ29vZCBpZGVhIHRvIHVzZSB0aGUgYHNldC5zZWVkKClgIGJhc2UgZnVuY3Rpb24gdG8gZW5zdXJlIHRoYXQgaWYgeW91ciByZXJ1biB5b3VyIGNvZGUgdGhhdCB5b3VyIHNwbGl0IHdpbGwgYmUgdGhlIHNhbWUgbmV4dCB0aW1lLiBXZSBjYW4gc2VlIHRoZSBudW1iZXIgb2YgbW9uaXRvcnMgaW4gb3VyIHRyYWluaW5nLCB0ZXN0aW5nLCBhbmQgb3JpZ2luYWwgZGF0YSBieSB0eXBpbmcgaW4gdGhlIG5hbWUgb2Ygb3VyIHNwbGl0IG9iamVjdC4gVGhlIHJlc3VsdCB3aWxsIGxvb2sgbGlrZSB0aGlzOgo8dHJhaW5pbmcgZGF0YSBzYW1wbGUgbnVtYmVyLCB0ZXN0aW5nIGRhdGEgc2FtcGxlIG51bWJlciwgb3JpZ2luYWwgc2FtcGxlIG51bWJlcj4gCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKcG1fc3BsaXQgPC1yc2FtcGxlOjppbml0aWFsX3NwbGl0KGRhdGEgPSBwbSwgcHJvcCA9IDIvMykKcG1fc3BsaXQKCiMgSWYgc3RyYXRpZnlpbmc6CiMgcG1fc3BsaXRfc3RyYXRhIDwtcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMsIHN0cmF0YSA9ICJzdGF0ZSIpCgpgYGAKCkltcG9ydGFudGx5IHRoZSBgaW5pdGlhbF9zcGxpdGAgZnVuY3Rpb24gb25seSBkZXRlcm1pbmVzIHdoYXQgcm93cyBvZiBvdXIgcG0gZGF0YSBmcmFtZSBzaG91bGQgYmUgYXNzaWduZWQgZm9yIHRyYWluaW5nIG9yIHRlc3RpbmcsIGl0IGRvZXMgbm90IGFjdHVhbGx5IHNwbGl0IHRoZSBkYXRhLiAKClRvIGV4dHJhY3QgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgd2UgY2FuIHVzZSB0aGUgYHRyYWluaW5nKClgIGFuZCBgdGVzdGluZygpYCBmdW5jdGlvbnMgYWxzbyBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQogdHJhaW5fcG0gPC1yc2FtcGxlOjp0cmFpbmluZyhwbV9zcGxpdCkKIHRlc3RfcG0gPC1yc2FtcGxlOjp0ZXN0aW5nKHBtX3NwbGl0KQogCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKY291bnQodHJhaW5fcG0sIHN0YXRlKQpjb3VudCh0ZXN0X3BtLCBzdGF0ZSkKYGBgCiMjIyMKCgoKIyMjIFZhcmlhYmxlIFJvbGUgQXNzaWdubWVudCBhbmQgUHJlcHJvY2Vzc2luZwoKSW4gdGlkeW1vZGVscyB3ZSB3aWxsIGNyZWF0ZSBhIHJlY2lwZSwgd2hpY2ggaXMgYSBzdGFuZGFyZGl6ZWQgZm9ybWF0IGZvciBhIHNlcXVlbmNlIG9mIHN0ZXBzIGZvciBwcm9jZXNzaW5nIHRoZSBkYXRhLgoKVGhpcyBjYW4gYmUgdmVyeSB1c2VmdWwgYmVjYXVzZSBpdCBtYWtlcyB0ZXN0aW5nIG91dCBkaWZmZXJlbnQgcHJlLXByb2Nlc3Npbmcgc3RlcHMgb3IgZGlmZmVyZW50IGFsZ29yaXRobXMgd2l0aCB0aGUgc2FtZSBwcmUtcHJvY2Vzc2luZyB2ZXJ5IGVhc3kgYW5kIHJlcHJvZHVjaWJsZS4KCioqQ3JlYXRpbmcgYSByZWNpcGUgc3BlY2lmaWVzIGhvdyBhIGRhdGFmcmFtZSBvZiBwcmVkaWN0b3JzIHNob3VsZCBiZSBjcmVhdGVkICAtIGl0IHNwZWNpZmllcyB3aGF0ICB2YXJpYWJsZXMgdG8gYmUgdXNlZCAgYW5kIHRoZSAgcHJlcHJvY2Vzc2luZyBzdGVwcyAgYnV0IGl0IGRvZXMgbm90IGV4ZWN1dGUgdGhlc2Ugc3RlcHMgb3IgY3JlYXRlIHRoZSBkYXRhZnJhbWUgb2YgcHJlZGljdG9ycy4qKgoKIyMjIyBMaXN0IHRoZSBpbmdyZWRpZW50cyAvIHNwZWNpZnkgdGhlIHZhcmlhYmxlcyB3aXRoIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uCgpUaGUgZmlyc3QgdGhpbmcgdG8gZG8gdG8gY3JlYXRlIGEgcmVjaXBlIGlzIHRvIHNwZWNpZnkgd2hpY2ggdmFyaWFibGVzIHdlIHdpbGwgYmUgdXNpbmcgYXMgb3VyIG91dGNvbWUgYW5kIHByZWRpY3RvcnMgdXNpbmcgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24uIEluIHRlcm1zIG9mIHRoZSBtZXRhcGhvciBvZiBiYWtpbmcsIHdlIGNhbiB0aGluayBvZiB0aGlzIGFzIGxpc3Rpbmcgb3VyIGluZ3JlZGllbnRzLiBUaGUgbmFtaW5nIGNvbnZlbnRpb24gZm9yIHJlY2lwZSBvYmplY3QgbmFtZXMgaXMgYCpfcmVjYCBvciBgcmVjYC4gCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInJlY2lwZXMxLnBuZyIpKQpgYGAKCgpJbiBvdXIgY2FzZSByZWNhbGwgdGhhdCBvdXIgYHZhbHVlYCB2YXJpYWJsZSwgd2hpY2ggaXMgdGhlIGF2ZXJhZ2UgYW5udWFsIGdyYXZpbWV0cmljIG1vbml0b3IgUE1+Mi41fiBjb25jZW50cmF0aW9uIGluIHVnL21eM14uIE91ciBwcmVkaWN0b3JzIGFyZSBhbGwgdGhlIG90aGVyIHZhcmlhYmxlcyBleGNlcHQgdGhlIG1vbml0b3IgSUQsIHdoaWNoIGlzIGFuIGBpZGAgdmFyaWFibGUuCgpUaGUgcmVhc29uIG5vdCB0byBpbmNsdWRlIHRoaXMgdmFyaWFibGUgaXMgYmVjYXVzZSB0aGlzIHZhcmlhYmxlIGluY2x1ZGVzIHRoZSBjb3VudHkgbnVtYmVyIGFuZCBhIG51bWJlciBkZXNpZ25hdGluZyB3aGljaCBwYXJ0aWN1bGFyIG1vbml0b3IgdGhlIHZhbHVlcyBjYW1lIGZyb20gb2YgdGhlIG1vbml0b3JzIHRoZXJlIGFyZSBpbiB0aGF0IGNvdW50eS4gU2luY2UgdGhpcyBudW1iZXIgaXMgYXJiaXRyYXJ5IGFuZCB0aGUgY291bnR5IGluZm9ybWF0aW9uIGlzIGFsc28gZ2l2ZW4gaW4gdGhlIGRhdGEsIGFuZCB0aGUgZmFjdCB0aGF0IGVhY2ggbW9uaXRvciBvbmx5IGhhcyBvbmUgdmFsdWUgaW4gdGhlIGB2YWx1ZWAgdmFyaWFibGUsIG5vdGhpbmcgaXMgZ2FpbmVkIGJ5IGluY2x1ZGluZyB0aGlzIHZhcmlhYmxlIGFuZCBpdCBtYXkgaW5zdGVhZCBpbnRyb2R1Y2Ugbm9pc2UuIEhvd2V2ZXIsIGl0IGlzIHVzZWZ1bCB0byBrZWVwIHRoaXMgZGF0YSB0byB0YWtlIGEgbG9vayBhdCB3aGF0IGlzIGhhcHBlbmluZyBsYXRlci4gV2Ugd2lsbCBzaG93IHlvdSB3aGF0IHRvIGRvIGluIHRoaXMgY2FzZSBpbiBqdXN0IGEgYml0LgoKVGhlIHNpbXBsZXN0IHJlY2lwZSB3aXRoIG5vIHByZXByb2Nlc3Npbmcgc3RlcHMsIHdvdWxkIGJlIHRvIHNpbXBseSBsaXN0IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3IgdmFyaWFibGVzLgoKV2UgY2FuIGRvIHNvIGluIHR3byB3YXlzOiAgCgoxKSBVc2luZyBmb3JtdWxhIG5vdGF0aW9uICAKMikgQXNzaWduaW5nIHJvbGVzIHRvIGVhY2ggdmFyaWFibGUgIAoKTGV0J3MgbG9vayBhdCB0aGUgZmlyc3Qgd2F5IHVzaW5nIGZvcm11bGEgbm90YXRpb24sIHdoaWNoIGxvb2tzIGxpa2UgdGhpczogIAoKb3V0Y29tZShzKSB+IHByZWRpY3RvcihzKSAgCgpJZiBpbiB0aGUgY2FzZSBvZiBtdWx0aXBsZSBwcmVkaWN0b3JzIG9yIGEgbXVsdGl2YXJpYXRlIHNpdHVhdGlvbiB3aXRoIHR3byBvdXRjb21lcywgdXNlIGEgcGx1cyBzaWduICAKCm91dGNvbWUxICsgb3V0Y29tZTIgfiBwcmVkaWN0b3IxICsgcHJlZGljdG9yMiAgCgpJZiB3ZSB3YW50IHRvIGluY2x1ZGUgYWxsIHByZWRpY3RvcnMgd2UgY2FuIHVzZSBhIHBlcmlvZCBsaWtlIHNvOiAgCgpvdXRjb21lX3ZhcmlhYmxlX25hbWUgfiAuICAKCk5vdyB3aXRoIG91ciBkYXRhIHdlIHdpbGwgc3RhcnQgYnkgbWFraW5nIGEgcmVjaXBlIGZvciBvdXIgdHJhaW5pbmcgZGF0YS4gSW4gdGhlIHNpbXBsZXN0IGNhc2Ugd2UgbWlnaHQgdXNlIGFsbCBwcmVkaWN0b3JzIGxpa2UgdGhpczoKCmBgYHtyfQoKc2ltcGxlX3JlYyA8LXRyYWluX3BtICU+JQogIHJlY2lwZXM6OnJlY2lwZSh2YWx1ZSB+IC4pCgpzaW1wbGVfcmVjCmBgYAoKCkhvd2V2ZXIsIHRvIGRlYWwgd2l0aCB0aGUgaWQgdmFyaWFibGUgd2UgY291bGQgdXNlIHRoZSBgdXBkYXRlX3JvbGUoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlOgoKYGBge3J9CgpzaW1wbGVfcmVjIDwtdHJhaW5fcG0gJT4lCiAgcmVjaXBlczo6cmVjaXBlKHZhbHVlIH4gLikgJT4lCiAgcmVjaXBlczo6dXBkYXRlX3JvbGUoaWQsIG5ld19yb2xlID0gImlkIHZhcmlhYmxlIikKCnNpbXBsZV9yZWMKYGBgCgpXZSBjb3VsZCBhbHNvIHNwZWNpZnkgdGhlIG91dGNvbWUgYW5kIHByZWRpY3RvcnMgaW4gdGhlIHNhbWUgd2F5IGFzIHRoZSBpZCB2YXJpYWJsZS4gUGxlYXNlIHNlZSBbaGVyZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9yZWNpcGUuaHRtbCkgZm9yIGV4YW1wbGVzIG9mIG90aGVyIHJvbGVzIGZvciB2YXJpYWJsZXMuIFRoZSByb2xlIGNhbiBiZSBhY3R1YWxseSBiZSBhbnkgdmFsdWUuIAoKVGhlIG9yZGVyIGlzIGltcG9ydGFudCBoZXJlLCBhcyB3ZSBmaXJzdCBtYWtlIGFsbCB2YXJpYWJsZXMgcHJlZGljdG9ycyBhbmQgdGhlbiBvdmVycmlkZSB0aGlzIHJvbGUgZm9yIHRoZSBvdXRjb21lIGFuZCBpZCB2YXJpYWJsZS4gV2Ugd2lsbCB1c2UgdGhlIGBldmVyeXRoaW5nKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc3RhcnQgd2l0aCBhbGwgb2YgdGhlIHZhcmlhYmxlcyBpbiBgdHJhaW5fcG1gLgoKYGBge3J9CgpzaW1wbGVfcmVjIDwtcmVjaXBlKHRyYWluX3BtKSAlPiUKICAgIHVwZGF0ZV9yb2xlKGV2ZXJ5dGhpbmcoKSwgbmV3X3JvbGUgPSAicHJlZGljdG9yIiklPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIiklPiUKICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpCgpzaW1wbGVfcmVjCgpgYGAKCklmIHdlIHdhbnQgdG8gdGFrZSBhIGxvb2sgYXQgb3VyIGZvcm11bGEgZnJvbSBvdXIgcmVjaXBlIHdlIGNhbiBkbyB1c2UgdGhlIGBmb3JtdWxhKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RhdHNgIHBhY2thZ2UuCgpgYGB7cn0KZm9ybXVsYShzaW1wbGVfcmVjKQpgYGAKCldlIGNhbiBhbHNvIHZpZXcgb3VyIHJlY2lwZSBpbiBtb3JlIGRldGFpbCB1c2luZyB0aGUgYmFzZSBgc3VtbWFyeSgpYCBmdW5jdGlvbi4KCmBgYHtyfQpzdW1tYXJ5KHNpbXBsZV9yZWMpCmBgYAoKIyMjIyBMaXN0IHRoZSBwcmVwcm9jZXNzaW5nIHN0ZXBzIHVzaW5nIHRoZSBzdGVwIGZ1bmN0aW9ucyBvZiB0aGUgYHJlY2lwZWAgcGFja2FnZQoKVGhlIG90aGVyIHRoaW5nIHRoZSByZWNpcGVzIHBhY2thZ2UgYWxsb3dzIGZvciBpcyBzcGVjaWZ5aW5nIHByZS1wcm9jZXNzaW5nIHN0ZXBzIHVzaW5nIGEgdmFyaWV0eSBvZiBgc3RlcCooKWAgZnVuY3Rpb25zLgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJyZWNpcGVzMi5wbmciKSkKYGBgCgoKKipUaGlzIFtsaW5rXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvcmVmZXJlbmNlL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gYW5kIHRoaXMgW2xpbmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZWNpcGVzL3JlY2lwZXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHNob3cgdGhlIG1hbnkgb3B0aW9ucyBmb3IgcmVjaXBlIHN0ZXAgZnVuY3Rpb25zLioqCgo8dT5UaGVyZSBhcmUgc3RlcCBmdW5jdGlvbnMgZm9yIGEgdmFyaWV0eSBvZiBwdXJwb3Nlczo8L3U+CgoxKSBbKipJbXB1dGF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ltcHV0YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAtLSB3aGljaCBtZWFucyBmaWxsaW5nIGluIG1pc3NpbmcgdmFsdWVzIGJhc2VkIG9uIHRoZSBleGlzdGluZyBkYXRhIAoyKSBbKipUcmFuc2Zvcm1hdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EYXRhX3RyYW5zZm9ybWF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgLS0gd2hpY2ggbWVhbnMgY2hhbmdpbmcgYWxsIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGluIHRoZSBzYW1lIHdheSwgdHlwaWNhbGx5IHRvIG1ha2UgaXQgbW9yZSBub3JtYWwgb3IgZWFzaWVyIHRvIGludGVycHJldCkgIAozKSBbKipEaXNjcmV0aXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXNjcmV0aXphdGlvbl9vZl9jb250aW51b3VzX2ZlYXR1cmVzKSAtLSB3aGljaCBtZWFucyBjb252ZXJ0aW5nIGNvbnRpbnVvdXMgdmFsdWVzIGludG8gZGlzY3JldGUgb3Igbm9taW5hbCB2YWx1ZXMgLSBiaW5uaW5nIGZvciBleGFtcGxlIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHBvc3NpYmxlIGxldmVscykgIChIb3dldmVyIHRoaXMgaXMgZ2VuZXJhbGx5IG5vdCBhZHZpc2FibGUhKQo0KSBbKipFbmNvZGluZyAvIENyZWF0aW5nIER1bW15IFZhcmlhYmxlcyoqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EdW1teV92YXJpYWJsZV8oc3RhdGlzdGljcykpIC0tIHdoaWNoIG1lYW5zIGNyZWF0aW5nIGEgbnVtZXJpYyBjb2RlIGZvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKWyoqTW9yZSBvbiBEdW1teSBWYXJpYWJsZXMgYW5kIG9uZSBob3QgZW5jb2RpbmcqKl0oaHR0cHM6Ly9tZWRpdW0uY29tL3AvYjU4NDBiZTNjNDFhL3Jlc3BvbnNlcy9zaG93KQo1KSBbKipEYXRhIHR5cGUgY29udmVyc2lvbnMqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2hhYmxhci92aWduZXR0ZXMvY29udmVydC5odG1sKSAtLSB3aGljaCBtZWFucyBjaGFuZ2luZyBmcm9tIGludGVnZXIgdG8gZmFjdG9yIG9yIG51bWVyaWMgdG8gZGF0ZSBldGMuCjYpIFsqKkludGVyYWN0aW9uKipdKGh0dHBzOi8vc3RhdGlzdGljc2J5amltLmNvbS9yZWdyZXNzaW9uL2ludGVyYWN0aW9uLWVmZmVjdHMvKSB0ZXJtIGFkZGl0aW9uIHRvIHRoZSBtb2RlbCAtLSB3aGljaCBtZWFucyB0aGF0IHdlIHdvdWxkIGJlIG1vZGVsaW5nIGZvciBwcmVkaWN0b3JzIHRoYXQgd291bGQgaW5mbHVlbmNlIHRoZSBjYXBhY2l0eSBvZiBlYWNoIG90aGVyIHRvIHByZWRpY3QgdGhlIG91dGNvbWUKNykgWyoqTm9ybWFsaXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob3JtYWxpemF0aW9uXyhzdGF0aXN0aWNzKSkgLS0gd2hpY2ggbWVhbnMgY2VudGVyaW5nIGFuZCBzY2FsaW5nIHRoZSBkYXRhIHRvIGEgc2ltaWxhciByYW5nZSBvZiB2YWx1ZXMKOCkgWyoqRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uLyBTaWduYWwgRXh0cmFjdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaW1lbnNpb25hbGl0eV9yZWR1Y3Rpb24pIC0tIHdoaWNoIG1lYW5zIG1hdGhlbWF0aWNhbGx5IG9idGFpbmluZyBhIG5ldyBzbWFsbGVyIHNldCBvZiB2YXJpYWJsZXMgdGhhdCBjYXB0dXJlIHRoZSB2YXJpYXRpb24gb3Igc2lnbmFsIGluIHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMgKGV4LiBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIGFuZCBJbmRlcGVuZGVudCBDb21wb25lbnQgQW5hbHlzaXMpCjkpICoqRmlsdGVyaW5nKiogLS0gRmlsdGVyaW5nIG9wdGlvbnMgZm9yIHJlbW92aW5nIHZhcmlhYmxlcyAoZXguIHJlbW92ZSB2YXJpYWJsZXMgdGhhdCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgdG8gb3RoZXJzIG9yIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCB2ZXJ5IGxpdHRsZSB2YXJpYW5jZSBhbmQgdGhlcmVmb3JlIGxpa2VseSBsaXR0bGUgcHJlZGljdGl2ZSBjYXBhY2l0eSkKMTApIFsqKlJvdyBvcGVyYXRpb25zKipdKGh0dHBzOi8vdGFydGFydXMub3JnL2dhcmV0aC9tYXRocy9MaW5lYXJfQWxnZWJyYS9yb3dfb3BlcmF0aW9ucy5wZGYpIC0tIHdoaWNoIG1lYW5zIHBlcmZvcm1pbmcgZnVuY3Rpb25zIG9uIHRoZSB2YWx1ZXMgd2l0aGluIHRoZSByb3dzICAoZXguIHJlYXJyYW5naW5nLCBmaWx0ZXJpbmcsIGltcHV0aW5nKQoxMSkgKipDaGVja2luZyBmdW5jdGlvbnMqKiAtLSBTYW5pdHkgY2hlY2tzIHRvIGxvb2sgZm9yIG1pc3NpbmcgdmFsdWVzLCB0byBsb29rIGF0IHRoZSB2YXJpYWJsZSBjbGFzc2VzIGV0Yy4KCkFsbCBvZiB0aGUgc3RlcCBmdW5jdGlvbnMgbG9vayBsaWtlIGBzdGVwXypgIGV4Y2VwdCBmb3IgdGhlIGNoZWNrIGZ1bmN0aW9ucyB3aGljaCBsb29rIGxpa2UgYGNoZWNrXypgLgoKVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBzZWxlY3Qgd2hhdCB2YXJpYWJsZXMgdG8gYXBwbHkgc3RlcHMgdG86ICAKMSkgdGlkeXNlbGVjdCBtZXRob2RzOiBgY29udGFpbnMoKWAsIGBtYXRjaGVzKClgLCBgc3RhcnRzX3dpdGgoKWAsIGBlbmRzX3dpdGgoKWAsIGBldmVyeXRoaW5nKClgLCBgbnVtX3JhbmdlKClgICAKMikgYmFzZWQgb24gdGhlIHR5cGU6IGBhbGxfbm9taW5hbCgpYCwgYGFsbF9udW1lcmljKClgICwgYGhhc190eXBlKClgIAozKSBiYXNlZCBvbiB0aGUgcm9sZTogYGFsbF9wcmVkaWN0b3JzKClgLCBgYWxsX291dGNvbWVzKClgLCBgaGFzX3JvbGUoKWAKNCkgbmFtZSAtIHVzZSB0aGUgYWN0dWFsIG5hbWUgb2YgdGhlIHZhcmlhYmxlL3ZhcmlhYmxlcyBvZiBpbnRlcmVzdCAgCgoKTGV0J3MgdHJ5IGFkZGluZyBzb21lIHN0ZXBzIHRvIG91ciByZWNpcGUuCgpXZSBtaWdodCBjb25zaWRlciBsb2cgdHJhbnNmb3JtaW5nIG91ciBwb3B1bGF0aW9uIGFuZCBhcmVhIHZhcmlhYmxlcyAodGhhdCBhcmVuJ3QgZGVuc2l0aWVzKSAtIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSByYW5nZSBvZiB0aGVzZSB2YXJpYWJsZXMuCmBgYHtyfQpwbSAlPiUKICBzZWxlY3QobWF0Y2hlcygiX3BvcHxfYXJlYSIpKSAlPiUKICBtYXAocmFuZ2UpCmBgYApXZSBjYW4gc2VlIHRoYXQgdGhlIHJhbmdlIGZvciBlYWNoIG9mIHRoZXNlIHZhcmlhYmxlcyBpcyBxdWl0ZSBsYXJnZSwgd2UgY2FuIGxvZyB0cmFuc2Zvcm0gdGhpcyBkYXRhIHVzaW5nIHRoZSBgc3RlcF9sb2coKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLgoKV2Ugd291bGQgYWxzbyB3YW50IHRvIHBvdGVudGlhbGx5IG9uZSBob3QgZW5jb2RlIHNvbWUgb2Ygb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBzbyB0aGF0IHRoZXkgY2FuIGJlIHVzZWQgd2l0aCBjZXJ0YWluIGFsZ29yaXRobXMuIFdlIGNhbiBkbyB0aGlzIHdpdGggdGhlIGBzdGVwX2R1bW15KClgIGZ1bmN0aW9uIGFuZCB0aGUgYG9uZV9ob3QgPSBUUlVFYCBhcmd1bWVudC4gT3VyIGZpcHMgdmFyaWFibGUgaW5jbHVkZXMgYSBudW1lcmljIGNvZGUgZm9yIHN0YXRlIGFuZCBjb3VudHkgLSBhbmQgdGhlcmVmb3JlIGlzIGVzc2VudGlhbGx5IGEgcHJveHkgZm9yIGNvdW50eS4gIFNpbmNlIHdlIGFscmVhZHkgaGF2ZSBjb3VudHksIHdlIHdpbGwganVzdCB1c2UgaXQgYW5kIGtlZXAgdGhlIGZpcHMgaWQgYXMgYW5vdGhlciBJRCB2YXJpYWJsZS4KCldlIGNhbiByZW1vdmUgdGhlIGBmaXBzYCB2YXJpYWJsZSBmcm9tIHRoZSBwcmVkaWN0b3JzIHVzaW5nIGB1cGRhdGVfcm9sZSgpYCB0byBtYWtlIHN1cmUgdGhhdCB0aGUgcm9sZSBpcyBubyBsb25nZXIgYCJwcmVkaWN0b3IiYC4gV2UgY2FuIG1ha2UgdGhlIHJvbGUgYW55dGhpbmcgd2Ugd2FudCBhY3R1YWxseSwgc28gd2Ugd2lsbCBrZWVwIGl0IHNvbWV0aGluZyBpZGVudGlmaWFibGUuCgpXZSBtaWdodCBhbHNvIHdhbnQgdG8gcmVtb3ZlIHZhcmlhYmxlcyB0aGF0IGFwcGVhciB0byBiZSByZWR1bmRhbnQgYW5kIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG90aGVycywgYXMgd2Uga25vdyBmcm9tIG91ciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHRoYXQgbWFueSBvZiBvdXIgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIuIFdlIGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBgc3RlcF9jb3JyKClgIGZ1bmN0aW9uLgoKKipJdCBpcyBpbXBvcnRhbnQgdG8gYWRkIHRoZSBzdGVwcyB0byB0aGUgcmVjaXBlIGluIGFuIG9yZGVyIHRoYXQgbWFrZXMgc2Vuc2UganVzdCBsaWtlIHdpdGggYSBjb29raW5nIHJlY2lwZS4qKgoKYGBge3J9CnNpbXBsZV9yZWMgJTw+JQogICNzdGVwX2xvZyhtYXRjaGVzKCJfcG9wfF9hcmVhIikpICU+JQogIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhKSAlPiUKICBzdGVwX2NvcnIoYWxsX251bWVyaWMoKSwgLSBDTUFRLCAtIGFvZCklPiUKICBzdGVwX256dihhbGxfbnVtZXJpYygpKSAKICAjc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhKQojICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKQogIyBjaGVja19uZXdfdmFsdWVzKGFsbF9wcmVkaWN0b3JzKCkpICU+JQogICNjaGVja19yYW5nZShhbGxfcHJlZGljdG9ycygpKQoKI2NhbiB1c2Ugc3RlcF9ybSgpIHRvIHJlbW92ZSBwcmVkaWN0b3JzCiAgCnNpbXBsZV9yZWMKYGBgCgoKIyMjIE9QVElPTkFMOiBSdW5uaW5nIHRoZSBwcmVwcm9jZXNzaW5nICh0byBzZWUgaXQpCgpUaGUgbmV4dCBtYWpvciBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgaXMgYHByZXAoKWAuCgpUaGlzIGZ1bmN0aW9uIHVwZGF0ZXMgdGhlIHJlY2lwZSBvYmplY3QgYmFzZWQgb24gdGhlIHRyYWluaW5nIGRhdGEuIEl0IGVzdGltYXRlcyBwYXJhbWV0ZXJzIChlc3RpbWF0aW5nIHRoZSByZXF1aXJlZCBxdWFudGl0aWVzIGFuZCBzdGF0aXN0aWNzIHJlcXVpcmVkIGJ5IHRoZSBzdGVwcyBmb3IgdGhlIHZhcmlhYmxlcykgZm9yIHByZXByb2Nlc3NpbmcgYW5kICB1cGRhdGVzIHRoZSBtb2RlbCB0ZXJtcywgYXMgc29tZSBvZiB0aGUgcHJlZGljdG9ycyBtYXkgYmUgcmVtb3ZlZCwgdGhpcyBhbGxvd3MgdGhlIHJlY2lwZSB0byBiZSByZWFkeSB0byB1c2Ugb24gb3RoZXIgZGF0YXNldHMuIEl0IGRvZXNuJ3QgbmVjZXNzYXJpbHkgYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcHJlcHJvY2Vzc2luZyBpdHNlbGYsIGhvd2V2ZXIgd2Ugd2lsbCBzcGVjaWZ5IGluIGFyZ3VtZW50IGZvciBpdCB0byBkbyB0aGlzIHNvIHRoYXQgd2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBwcmVwcm9jZXNzZWQgZGF0YS4KClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBhcmd1bWVudHMgdG8ga25vdyBhYm91dDoKMSkgdHJhaW5pbmcgLSB5b3UgbXVzdCBzdXBwbHkgYSB0cmFpbmluZyBkYXRhIHNldCB0byBlc3RpbWF0ZSBwYXJhbWV0ZXJzIGZvciBwcmVwcm9jZXNzaW5nIG9wZXJhdGlvbnMgKHJlY2lwZSBzdGVwcykgLSB0aGlzIG1heSBhbHJlYWR5IGJlIGluY2x1ZGVkIGluIHlvdXIgcmVjaXBlIC0gYXMgaXMgdGhlIGNhc2UgZm9yIHVzCjIpIGZyZXNoIC0gaWYgVFJVRSAtIHdpbGwgcmV0cmFpbiBhbmQgZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgYW55IHByZXZpb3VzIHN0ZXBzIHRoYXQgd2VyZSBhbHJlYWR5IHByZXBwZWQgaWYgeW91IGFkZCBtb3JlIHN0ZXBzIHRvIHRoZSByZWNpcGUKMykgdmVyYm9zZSAtIGlmIGBUUlVFYCBzaG93cyB0aGUgcHJvZ3Jlc3MgYXMgdGhlIHN0ZXBzIGFyZSBldmFsdWF0ZWQgYW5kIHRoZSBzaXplIG9mIHRoZSBwcmVwcm9jZXNzZWQgdHJhaW5pbmcgc2V0CjQpIHJldGFpbiAtIGlmIGBUUlVFYCB0aGVuIHRoZSBwcmVwcm9jZXNzZWQgdHJhaW5pbmcgc2V0IHdpbGwgYmUgc2F2ZWQgd2l0aGluIHRoZSByZWNpcGUgKGFzIHRlbXBsYXRlKS4gVGhpcyBpcyBnb29kIGlmIHlvdSBhcmUgbGlrZWx5IHRvIGFkZCBtb3JlIHN0ZXBzIGFuZCBkb24ndCB3YW50IHRvIHJlcnVuIHRoZSBgcHJlcCgpYCBvbiB0aGUgcHJldmlvdXMgc3RlcHMuIEhvd2V2ZXIgdGhpcyBjYW4gbWFrZSB0aGUgcmVjaXBlIHNpemUgbGFyZ2UuIFRoaXMgaXMgbmVjZXNzYXJ5IGlmIHlvdSB3YW50IHRvIGFjdHVhbGx5IGxvb2sgYXQgdGhlIHByZXByb2Nlc3NlZCBkYXRhLgoKCmBgYHtyfQpwcmVwcGVkX3JlYyA8LSBwcmVwKHNpbXBsZV9yZWMsIHZlcmJvc2UgPSBUUlVFLCByZXRhaW4gPSBUUlVFICkKbmFtZXMocHJlcHBlZF9yZWMpCmBgYAoKVGhlcmUgYXJlIGFsc28gbG90cyBvZiB1c2VmdWwgdGhpbmdzIHRvIGNoZWNrb3V0IGluIHRoZSBvdXRwdXQgb2YgYHByZXAoKWAuCllvdSBjYW4gc2VlOgoxKSB0aGUgYHN0ZXBzYCB0aGF0IHdlcmUgcnVuICAKMikgdGhlIHZhcmlhYmxlIGluZm8gKGB2YXJfaW5mb2ApICAKMykgdGhlIG1vZGVsIGB0ZXJtX2luZm9gCjQpIHRoZSBuZXcgYGxldmVsc2Agb2YgdGhlIHZhcmlhYmxlcyAKNSkgdGhlIG9yaWdpbmFsIGxldmVscyBvZiB0aGUgdmFyaWFibGVzIGBvcmlnX2x2bHNgICAgCjYpIGluZm8gYWJvdXQgdGhlIHRyYWluaW5nIGRhdGEgc2V0IHNpemUgYW5kIGNvbXBsZXRlbmVzcyAoYHRyX2luZm9gKQoKTm90ZTogIFlvdSBtYXkgc2VlIHRoZSBgcHJlcC5yZWNpcGUoKWAgZnVuY3Rpb24gaW4gbWF0ZXJpYWwgdGhhdCB5b3UgcmVhZCBhYm91dCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuIFRoaXMgaXMgcmVmZXJyaW5nIHRvIHRoZSBgcHJlcCgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCgojIyMjIEV4dHJhY3RpbmcgdGhlIHByZXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInJlY2lwZXMzLnBuZyIpKQpgYGAKClNpbmNlIHdlIHJldGFpbmVkIG91ciBwcmVwcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSwgd2UgY2FuIHRha2UgYSBsb29rIGF0IGl0IGxpa2UgYnkgdXNpbmcgdGhlIGBqdWljZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgbGlrZSB0aGlzOgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhlcm91Z2ggdGhlIG91dHB1dCEKcHJlcHBlZF90cmFpbjwtIGp1aWNlKHByZXBwZWRfcmVjKQpnbGltcHNlKHByZXBwZWRfdHJhaW4pCmBgYAojIyMjCgoKRm9yIGVhc3kgY29tcGFyaXNvbiBzYWtlIC0gaGVyZSBpcyBvdXIgb3JpZ2luYWwgZGF0YToKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhlcm91Z2ggdGhlIG91dHB1dCEKZ2xpbXBzZShwbSkKYGBgCiMjIyMKCk5vdGljZSBob3cgd2Ugb25seSBoYXZlIDM2IHZhcmlhYmxlcyBub3cgaW5zdGVhZCBvZiA1MCEgVHdvIG9mIHRoZXNlIGFyZSBvdXIgSUQgdmFyaWFibGVzIChgZmlwc2AgYW5kIHRoZSBhY3R1YWwgbW9uaXRvciBJRCAoYGlkYCkpIGFuZCBvbmUgaXMgb3VyIG91dGNvbWUgKGB2YWx1ZWApLiBUaHVzIHdlIG9ubHkgaGF2ZSAzMyBwcmVkaWN0b3JzIG5vdy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgdmFyaWFibGVzIHRoYXQgd2Ugbm8gbG9uZ2VyIGhhdmUgYW55IGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gVmFyaWFibGVzIGxpa2UgYHN0YXRlYCBhcmUgZ29uZSBhbmQgb25seSBgc3RhdGVfQ2FsaWZvcm5pYWAgcmVtYWlucyBhcyBpdCB3YXMgdGhlIG9ubHkgc3RhdGUgaWRlbnRpdHkgdG8gaGF2ZSBub256ZXJvIHZhcmlhbmNlLiAgV2UgY2FuIHNlZSB0aGF0IENhbGlmb3JuaWEgaGFkIHRoZSBsYXJnZXN0IG51bWJlciBvZiBtb25pdG9ycyBjb21wYXJlZCB0byB0aGUgb3RoZXIgc3RhdGVzLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGVyZSB3ZXJlIG1vcmUgbW9uaXRvcnMgbGlzdGVkIGFzIGAiTm90IGluIGEgY2l0eSJgIHRoYW4gYW55IGNpdHkuIAoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KcG0gJT4lIGNvdW50KHN0YXRlKQpwbSAlPiUgY291bnQoY2l0eSkKYGBgCiMjIyMKCioqTm90ZSoqOiAgUmVjYWxsIHRoYXQgeW91IG11c3Qgc3BlY2lmeSBgcmV0YWluID0gVFJVRWAgYXJndW1lbnQgb2YgdGhlIGBwcmVwKClgIGZ1bmN0aW9uIHRvIHVzZSBganVpY2UoKWAuCgojIyMjIEV4dHJhY3RpbmcgdGhlIHByZXByb2Nlc3NlZCB0ZXN0aW5nIGRhdGEKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwicmVjaXBlczQucG5nIikpCmBgYAoKTGF0ZXIgb24gaWYgeW91IHdhbnQgdG8gbG9vayBhdCB0aGUgcHJlcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB5b3Ugd291bGQgdXNlIHRoZSBgYmFrZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UgbGlrZSB0aGlzOgoKSG93ZXZlciB5b3Ugd291bGQgd2FudCB0byBsZWF2ZSB5b3VyIHRlc3RpbmcgZGF0YSBhbG9uZSBhdCB0aGlzIHBvaW50LgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhlcm91Z2ggdGhlIG91dHB1dCEKYmFrZWRfcmVjIDwtIHJlY2lwZXM6OmJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gdGVzdF9wbSkKZ2xpbXBzZShiYWtlZF9yZWMpCmBgYAojIyMjCgo+IGJha2UoKSB0YWtlcyBhIHRyYWluZWQgcmVjaXBlIGFuZCBhcHBsaWVzIHRoZSBvcGVyYXRpb25zIHRvIGEgZGF0YSBzZXQgdG8gY3JlYXRlIGEgZGVzaWduIG1hdHJpeC4KIGZvciBleGFtcGxlOiAgaXQgYXBwbGllcyB0aGUgY2VudGVyaW5nIHRvIG5ldyBkYXRhIHNldHMgdXNpbmcgdGhlc2UgbWVhbnMgdXNlZCB0byBjcmVhdGUgdGhlIHJlY2lwZQoKCk5vdGU6IGlmIHlvdSB1c2UgdGhlIHNraXAgb3B0aW9uIGZvciBzb21lIG9mIHRoZSBwcmVwcm9jZXNzaW5nIHN0ZXBzLCBiZSBjYXJlZnVsLiBganVpY2UoKWAgd2lsbCBzaG93IGFsbCBvZiB0aGUgcmVzdWx0cyBpZ25vcmluZyBgc2tpcCA9IFRSVUVgLiBgYmFrZSgpYCB3aWxsIG5vdCBuZWNlc3NhcmlseSBjb25kdWN0IHRoZXNlIHN0ZXBzIG9uIHRoZSBuZXcgZGF0YS4gCgoKCiMjIyBTcGVjaWZ5aW5nIHRoZSBNb2RlbAoKU28gZmFyIHdlIGhhdmUgdXNlZCBgcnNhbXBsZWAgdG8gc3BsaXQgdGhlIGRhdGEgYW5kIGByZWNpcGVzYCB0byBhc3NpZ24gdmFyaWFibGUgYW5kIHRvIHNwZWNpZnkgYW5kIHByZXAgb3VyIHByZXByb2Nlc3NpbmcgKGFzIHdlbGwgYXMgdG8gb3B0aW9uYWxseSBleHRyYWN0IHRoZSBwcmVwcm9jZXNzZWQgZGF0YSkuCgpXZSB3aWxsIG5vdyB1c2UgdGhlIGBwYXJzbmlwYCBwYWNrYWdlICh3aGljaCBpcyBzaW1pbGFyIHRvIHRoZSBwcmV2aW91cyBgY2FyZXRgIHBhY2thZ2UgLSBhbmQgaGVuY2Ugd2h5IGl0IGlzIG5hbWVkIGFmdGVyIHRoZSB2ZWdldGFibGUpIHRvIHNwZWNpZnkgb3VyIG1vZGVsLgoKVGhlcmUgYXJlIGZvdXIgYXNwZWN0cyB0byBkZWZpbmUgYWJvdXQgb3VyIG1vZGVsOiAgCjEpIHRoZSAqKnR5cGUqKiBvZiBtb2RlbCAodXNpbmcgc3BlY2lmaWMgZnVudGlvbnMgaW4gcGFyc25pcCBsaWtlIGByYW5kX2ZvcmVzdCgpYCwgYGxvZ2lzdGljX3JlZygpYCBldGMuKSAgCjIpIHRoZSAqKm1vZGUqKiBvZiBsZWFybmluZyAtIGNsYXNzaWZpY2F0aW9uIG9yIHJlZ3Jlc3Npb24gKHVzaW5nIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24pICAKMykgdGhlIHBhY2thZ2Ugb3IgKiplbmdpbmUqKiB0aGF0IHdlIHdpbGwgdXNlIHRvIGltcGxlbWVudCB0aGUgdHlwZSBvZiBtb2RlbCBzZWxlY3RlZCAodXNpbmcgdGhlIGBzZXRfZW5naW5lKClgIGZ1bmN0aW9uKSAgCjQpIGFueSAqKmFyZ3VtZW50cyoqIG5lY2Vzc2FyeSBmb3IgdGhlIG1vZGVsL3BhY2thZ2Ugc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2FyZ3MoKWBmdW5jdGlvbiAtICBmb3IgZXhhbXBsZSB0aGUgYG10cnkgPWAgYXJndW1lbnQgZm9yIHJhbmRvbSBmb3Jlc3Qgd2hpY2ggaXMgdGhlIG51bWJlciBvZiB2YXJpYWJsZXMgdG8gYmUgdXNlZCBhcyBvcHRpb25zIGZvciBzcGxpdHRpbmcgYXQgZWFjaCB0cmVlIG5vZGUpICAKCldlIGFyZSBnb2luZyB0byBzdGFydCBvdXIgYW5hbHlzaXMgd2l0aCBhIGxpbmVhciByZWdyZXNzaW9uIGJ1dCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGhvdyB3ZSBjYW4gdHJ5IGRpZmZlcmVudCBtb2RlbHMuCgpUaGUgZmlyc3QgdGhpbmcgd2UgZG8gaXMgZGVmaW5lIHdoYXQgdHlwZSBvZiBtb2RlbCB3ZSB3b3VsZCBsaWtlIHRvIHVzZS4gU2VlIFtoZXJlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvYXJ0aWNsZXMvYXJ0aWNsZXMvTW9kZWxzLmh0bWwKKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb2RlbGluZyBbb3B0aW9uc11pbiBwYXJzbmlwLgoKYGBge3J9ClBNX21vZGVsIDwtIHBhcnNuaXA6OmxpbmVhcl9yZWcoKSAjUE0gZm9yIHBhcnRpY3VsYXRlIG1hdGVyClBNX21vZGVsCmBgYAoKT0suIFNvIGZhciBhbGwgd2UgaGF2ZSB0b2xkIGBwYXJzbmlwYCBpcyB3ZSB3YW50IHRvIHVzZSBhIGxpbmVhciByZWdyZXNzaW9uLi4uICBMZXQncyB0ZWxsIGBwYXJzbmlwYCBtb3JlIGFib3V0IHdoYXQgd2Ugd2FudC4KCldlIHdvdWxkIGxpa2UgdG8gdXNlIHRoZSBvcmRpbmFyeSBsZWFzdCBzcXVhcmVzIG1ldGhvZCB0byBmaXQgb3VyIGxpbmVhciByZWdyZXNzaW9uLiBTbyB3ZSB3aWxsIHRlbGwgYHBhcnNuaXBgIHRoYXQgd2Ugd2FudCB0byB1c2UgdGhlIGBsbWAgcGFja2FnZSB0byBpbXBsZW1lbnQgb3VyIGxpbmVhciByZWdyZXNzaW9uICh0aGVyZSBhcmUgbWFueSBvcHRpb25zIGFjdHVhbGx5LSBzdWNoIGFzIFtgcnN0YW5gXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnN0YW4vdmlnbmV0dGVzL3JzdGFuLmh0bWwpIFtgZ2xtbmV0YF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dsbW5ldC9pbmRleC5odG1sKSwgW2BrZXJhc2BdKGh0dHBzOi8va2VyYXMucnN0dWRpby5jb20vKSwgYW5kIFtgc3BhcmtseXJgXShodHRwczovL3RoZXJpbnNwYXJrLmNvbS9zdGFydGluZy5odG1sI3N0YXJ0aW5nLXNwYXJrbHlyLWhlbGxvLXdvcmxkKSkuIFdlIHdpbGwgZG8gc28gYnkgdXNpbmcgdGhlIGBzZXRfZW5naW5lKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZS4KCmBgYHtyfQpsbV9QTV9tb2RlbCA8LSAKICBQTV9tb2RlbCAgJT4lCiAgcGFyc25pcDo6c2V0X2VuZ2luZSgibG0iKQoKbG1fUE1fbW9kZWwKCmBgYAoKSW4gc29tZSBjYXNlcyBzb21lIHBhY2thZ2VzIGNhbiBkbyBlaXRoZXIgY2xhc3NpZmljYXRpb24gb3IgcHJlZGljdGlvbiwgc28gaXQgaXMgYSBnb29kIGlkZWEgdG8gc3BlY2lmeSB3aGljaCBtb2RlIHlvdSBpbnRlbmQgdG8gcGVyZm9ybS4gWW91IGNhbiBkbyB0aGlzIHdpdGggdGhlIGBzZXRfbW9kZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UsIGJ5IHVzaW5nIGVpdGhlciBgc2V0X21vZGUoImNsYXNzaWZpY2F0aW9uIilgIG9yIGBzZXRfbW9kZSgicmVncmVzc2lvbiIpYC4KCmBgYHtyfQpsbV9QTV9tb2RlbCA8LSAKICBQTV9tb2RlbCAgJT4lCiAgcGFyc25pcDo6c2V0X2VuZ2luZSgibG0iKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCgpsbV9QTV9tb2RlbAoKYGBgCgojIyMgRml0dGluZyB0aGUgTW9kZWwgd2l0aCBgd29ya2Zsb3dzYCBhbmQgYHBhcnNuaXBgCgpUbyBmaXQgb3VyIG1vZGVsIHdlIGNvdWxkIHVzZSBgcGFyc25pcGAgYW5kIHRoZW4gYXNzZXNzIG91ciBmaXQgdXNpbmcgdGhlIGB5YXJkc3RpY2tgIHBhY2thZ2UuCgpIb3dldmVyIGEgbmV3ZXIgcGFja2FnZSBjYWxsZWQgYHdvcmtmbG93c2AgYWxsb3dzIHVzIHRvIGtlZXAgdHJhY2sgb2YgYm90aCBvdXIgcHJlcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb24uIEl0IGFsc28gYWxsb3dzIHVzIHRvIGltcGxlbWVudCBmYW5jaWVyIG9wdGltaXphdGlvbnMgaW4gYW4gYXV0b21hdGVkIHdheSBhbmQgaXQgaXMgY3VycmVudGx5IGJlaW5nIGRldmVsb3BlZCB0byBhbHNvIGhhbmRsZSBwb3N0LXByb2Nlc3Npbmcgb3BlcmF0aW9ucywgc28gaXQgaXMgZ29vZCB0byBsZWFybiBhYm91dCBpdCEKClNvIHdlIHdpbGwgbm93IGNyZWF0ZSBhIHdvcmtmbG93IHdpdGggdGhlIHJlY2lwZSAob3VyIHByZXByb2Nlc3Npbmcgc3BlY2lmaWNhdGlvbnMpIHRoYXQgd2UgbWFkZSBhbmQgdGhlIG1vZGVsIHRoYXQgd2UganVzdCBzcGVjaWZpZWQuCgpGaXJzdCB3ZSB1c2UgdGhlIGB3b3JrZmxvdygpYCBmdW5jdGlvbiBvZiB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSB0byBjcmVhdGUgYSB3b3JrZmxvdy4KClRoZW4gd2UgYWRkIG91ciByZWNpcGUgd2l0aCB0aGUgYGFkZF9yZWNpcGUoKWAgZnVuY3Rpb24gYW5kIHdlIGFkZCBvdXIgbW9kZWwgd2l0aCB0aGUgYGFkZF9tb2RlbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHdvcmtmbG93c2AgcGFja2FnZS4gCgpOb3RlOiBXZSBkbyBub3QgbmVlZCB0byBhY3R1YWxseSBwcmVwIG91ciByZWNpcGUgYmVmb3JlIHVzaW5nIHdvcmtmbG93cyEKCmBgYHtyfQpQTV93ZmxvdyA8LXdvcmtmbG93czo6d29ya2Zsb3coKSAlPiUKICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoc2ltcGxlX3JlYykgJT4lCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwobG1fUE1fbW9kZWwpClBNX3dmbG93CmBgYAoKQWgsIG5pY2UuIE5vdGljZSBob3cgaXQgdGVsbHMgdXMgYWJvdXQgYm90aCBvdXIgcHJlcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb25zLgoKTm93IHdlIGNhbiBwcmVwYXJlIHRoZSByZWNpcGUgKGVzdGltYXRlIHRoZSBwYXJhbWV0ZXJzKSBhbmQgZml0IHRoZSBtb2RlbCB0byBvdXIgdHJhaW5pbmcgZGF0YSBhbGwgYXQgb25jZS4gUHJpbnRpbmcgdGhlIG91dHB1dCB3ZSBjYW4gc2VlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIG1vZGVsLgoKYGBge3J9ClBNX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUE1fd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKUE1fd2Zsb3dfZml0CmBgYAoKT3RoZXJ3aXNlIHdlIGNvdWxkIGhhdmUgZG9uZSB0aGlzIHdpdGhvdXQgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2U6CmBgYHtyfQpQTV9maXQgPC0gbG1fUE1fbW9kZWwgJT4lIAogIHBhcnNuaXA6OmZpdCh2YWx1ZSB+LiwgZGF0YSA9cHJlcHBlZF90cmFpbikKCmBgYAoKIyMjIExvb2tpbmcgYXQgbW9kZWwgZml0IHdpdGggYGJyb29tYAoKVGhlIGBicm9vbWAgcGFja2FnZSBhbGxvd3MgZm9yIGFuIGVhc3kvdGlkeSB3YXkgdG8gbG9vayBhdCB0aGUgZml0dGVkIG1vZGVsOiAgCgpgdGlkeSgpYCBncmFicyB0aGUgY29lZmZpY2llbnRzIGZyb20gdGhlIG1vZGVsICAKYGdsYW5jZSgpYCBzdW1tYXJpemVzIHRoZSBtb2RlbCBmaXQgIApgYXVnbWVudCgpYCBnaXZlcyBhIDE1MCByb3cgb2JzZXJ2YXRpb24gbGV2ZWwgc3VtbWFyeSAgCgpUaGVzZSBgYnJvb21gIGZ1bmN0aW9ucyBjdXJyZW50bHkgb25seSB3b3JrIHdpdGggYHBhcnNuaXBgIG9iamVjdHMgbm90IHJhdyBgd29ya2Zsb3dzYCBvYmplY3RzLiBUbyB1c2UgdGhlc2UgZnVuY3Rpb25zIHdpdGggYHdvcmtmbG93c2Agd2UgbmVlZCB0byBmaXJzdCB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4KCmBgYHtyfQpicm9vbTo6dGlkeShQTV9maXQpCmJyb29tOjpnbGFuY2UoUE1fZml0JGZpdCkKYnJvb206OmF1Z21lbnQoUE1fZml0JGZpdCkKCgpQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHRpZHkoKQpgYGAKCgpPSywgc28gd2UgaGF2ZSBmaXQgb3VyIG1vZGVsIG9uIG91ciB0cmFpbmluZyBkYXRhLCB3aGljaCBtZWFucyB3ZSBoYXZlIGNyZWF0ZWQgYSBtb2RlbCB0byBwcmVkaWN0IHZhbHVlcyBvZiBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uIHRoZSBwcmVkaWN0b3JzIHRoYXQgd2UgaGF2ZSBpbmNsdWRlZC4gWWF5IQoKCkF0IHRoaXMgcG9pbnQgd2UgY291bGQgdGFrZSBhIGxvb2sgYXQgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbCBwZXJmb3JtYW5jZSwgYnV0IHdlIHdpbGwgb25seSBoYXZlIG9uZSByZWZlcmVuY2UgcG9pbnQ6IG91ciB0ZXN0aW5nIGRhdGFzZXQuIEFuZCB3ZSBoYXZlbid0IGRvbmUgYW55IHR1bmluZyBvZiBvdXIgbW9kZWwgb3IgY3Jvc3MgdmFsaWRhdGlvbi4uLiBzbyBnZW5lcmFsbHkgc3BlYWtpbmcgeW91IDx1Pioqc2hvdWxkIG5vdCoqPC91PiBkbyB0aGlzLiAKCkhvd2V2ZXIgaWYgeW91IHdlcmUgc2hvcnQgb24gdGltZSB5b3UgY291bGQgY29udGludWUgbGlrZSB0aGlzLgoKbmVlZCB0dW5lXyooKSwgZml0X3Jlc2FtcGxlcygpIG9yIGxhc3RfZml0KCkgdG8gZ2V0IGFueSBhc3Nlc3NtZW50IG9mIGZpdC4KCgpXZSBjb3VsZCBzdG9wIGhlcmUgYW5kIHVzZSB0aGUgYHlhcmRzdGlja2AgcGFja2FnZSB0byBldmFsdWF0ZSBwZXJmb3JtYW5jZS4gRmlyc3Qgd2Ugd291bGQgd2FudCB0byBmaXQgdGhlIG1vZGVsIHdpdGggaG1tbSBub3Qgc3VyZSBpZiBJIHdpbGwgZG8gdGhpcyBvciBqdXN0IHNraXAgYW5kIHVzZSB0dW5lIGV2ZW4gaWYgd2UgZG9udCBoYXZlIGFueSB0dW5pbmc/PwoKVXNpbmcgcGFyc25pcCB3ZSBuZWVkIHRvIHVzZSB0aGUgYmFrZWQgZGF0YSB0ZXN0aW5nIGRhdGEuLi4gb3Igbm90Pz8/CmBgYHtyfQojIGxtX2ZpdCA8LWxtX1BNX21vZGVsICU+JQojICAgcGFyc25pcDo6Zml0KHZhbHVlIH4uLGRhdGEgPSBqdWljZWRfcmVjKQojeWFyZHN0aWNrOjptZXRyaWNzKGxtX2ZpdCwgdHJ1dGgsIHByZWRpY3RlZCkKCiMgdmFsdWVzX3ByZWQgPC0gCiMgICBwcmVkaWN0KFBNX3dmbG93X2ZpdCwgYmFrZWRfcmVjKSAlPiUgCiMgICBiaW5kX2NvbHMoYmFrZWRfcmVjICU+JSBzZWxlY3QodmFsdWUsIGZpcHMpKSAKIyB2YWx1ZXNfcHJlZAoKCnZhbHVlc19wcmVkIDwtIAogIHByZWRpY3QoUE1fd2Zsb3dfZml0LCB0ZXN0X3BtKSAlPiUgCiAgYmluZF9jb2xzKHRlc3RfcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcykpIAp2YWx1ZXNfcHJlZAojV2l0aCBUdW5lIHBhY2thZ2U6CiNvdmVyYWxsZml0IDwtdHVuZTo6bGFzdF9maXQoUE1fd2Zsb3csIHBtX3NwbGl0KQojY291bnQodmFsdWVzX3ByZWQsIC5wcmVkKQpgYGAKCgpTYXkgd2Ugd2VyZSBkb25lIG9wdGltaXppbmcgb3VyIHBhcmFtZXRlcnMgd2UgY291bGQgdGhlbiB1c2UgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHdvcmtmbG93c2AgcGFja2FnZS4KCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiNvdmVyYWxsZml0IDwtdHVuZTo6bGFzdF9maXQoUE1fd2Zsb3csIHBtX3NwbGl0KQogIyBvcgojb3ZlcmFsbGZpdCA8LVBNX3dmbG93ICU+JQojICB0dW5lOjpsYXN0X2ZpdChwbV9zcGxpdCkKCiMjb3ZlcmFsbGZpdApgYGAKCldlIGNvdWxkIGNoZWNrIG91dCB0ZXN0IHBlcmZvcm1hbmNlIHVzaW5nIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4KCm1vZGVsIHBlcmZvcm1hbmNlIDpodHRwczovL21lZGl1bS5jb20vQGxpbWF2YWxsYW50aW4vbWV0cmljcy10by1tZWFzdXJlLW1hY2hpbmUtbGVhcm5pbmctbW9kZWwtcGVyZm9ybWFuY2UtZThjOTYzNjY1NDc2CgpgYGB7cn0KI3Rlc3RfcGVyZm9ybWFuY2UgPC0gb3ZlcmFsbGZpdCAgJT4ldHVuZTo6Y29sbGVjdF9tZXRyaWNzKCkKI3Rlc3RfcGVyZm9ybWFuY2UKYGBgCgpIZXJlIHlvdSBjYW4gc2VlIHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHRlc3Qgc2V0ICh0aGUgMjkyIHJvd3Mgd2l0aCBwcmVkaWNpdGlvbnMgb3V0IG9mIHRoZSA4NzYgb3JpZ2luYWwgbW9uaXRvciB2YWx1ZXMpIGFsc28gdXNpbmcgdGhlIGB0dW5lYCBwYWNrYWdlIHdpdGggdGhlIGBjb2xsZWN0X3ByZWRpY3Rpb25zKClgIGZ1bmN0aW9uLgoKYGBge3J9CiN0ZXN0X3ByZWRpY3Rpb25zIDwtIG92ZXJhbGxmaXQgICU+JXR1bmU6OmNvbGxlY3RfcHJlZGljdGlvbnMoKQojcHJpbnQodGVzdF9wcmVkaWN0aW9ucywgbj0xZTMpCmBgYAojIyMjCgoKSG93ZXZlciB3ZSB3b3VsZCByZWFsbHkgd2FudCB0byB0dW5lIHBhcmFtZXRlcnMgYW5kIHVzZSBjcm9zcyB2YWxpZGF0aW9uIGZvciB0aGlzLgoKCgp5YXJkc3RpY2sgY2FuJ3QgdGFsayBkaXJlY3RseSB0byB3b3JrZmxvd3MuLi4gbmVlZCB0dW5lIGZvciB0aGF0Li4uCgoKCiMjIyBDcm9zcyB2YWxpZGF0aW9uIHNhbXBsZSBzcGxpdHRpbmcKCldlIHdpbGwgdXNlIHRoZSBgcnNhbXBsZWAgcGFja2FnZSBhZ2FpbiBpbiBvcmRlciB0byBmdXJ0aGVyIGltcGxlbWVudCB3aGF0IGFyZSBjYWxsZWQgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHRlY2huaXF1ZXMuIFRoaXMgaXMgYWxzbyBjYWxsZWQgKipyZXNhbXBsaW5nKiogb3IgKipyZXBhcnRpb25pbmcqKi4KTm90ZTogd2UgYXJlIG5vdCBhY3R1YWxseSBnZXR0aW5nIG5ldyBzYW1wbGVzIGZyb20gdGhlIHVuZGVybHlpbmcgZGlzdHJpYnV0aW9uIHNvIHRoZSB0ZXJtIHJlc2FtcGxpbmcgaXMgYSBiaXQgb2YgYSBtaXNub21lci4KCltDcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBzcGxpdHMgb3VyIHRyYWluaW5nIGRhdGEgaW50byBtdWx0aXBsZSB0cmFpbmluZyBkYXRhIHNldHMgdG8gYWxsb3cgZm9yIGFuIGFzc2Vzc21lbnQgb2YgdGhlIGFjY3VyYWN5IG9mIHRoZSBtb2RlbC4KCkhlcmUgaXMgYSB2aXN1YWxpemF0aW9uIG9mIHRoZSBjb25jZXB0IGZvciBjcm9zcyB2YWxpZGF0aW9uL3Jlc2FtcGxpbmcvcmVwYXJ0aXRpb25pbmcgZnJvbSBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn06CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInJlc2FtcGxpbmcucG5nIikpCmBgYAoKVGVjaG5pY2FsbHkgY3JlYXRpbmcgb3VyIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldCBvdXQgb2Ygb3VyIG9yaWdpbmFsIHRyYWluaW5nIGRhdGEgaXMgc29tZXRpbWVzIGNvbnNpZGVyZWQgYSBmb3JtIG9mIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBjYWxsZWQgdGhlIGhvbGRvdXQgbWV0aG9kLiBBcyB3ZSBqdXN0IGxlYXJuZWQgdGhpcyBjYW4gZ2l2ZSB1cyBhIGJldHRlciBzZW5zZSBvZiB0aGUgYWNjdXJhY3kgb2Ygb3VyIGRhdGEgaW4gYSBtb3JlIGdlbmVyYWxpemFibGUgd2F5LiAKCkhvd2V2ZXIsIHdlIGNhbiBkbyBhIGJldHRlciBqb2Igb2Ygb3B0aW1pemluZyBvdXIgbW9kZWwgZm9yIGFjY3VyYWN5IGlmIHdlIGFsc28gcGVyZm9ybSBhbm90aGVyIHR5cGUgb2YgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IG9uIHRoZSBuZXdseSBkZWZpbmVkIHRyYWluaW5nIHNldCB0aGF0IHdlIGp1c3QgY3JlYXRlZC4gVGhlcmUgYXJlIG1hbnkgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IG1ldGhvZHMgYW5kIG1vc3QgY2FuIGJlIGVhc2lseSBpbXBsZW1lbnRlZCB1c2luZyBgcnNhbXBsZXNgIHBhY2thZ2UuIFdlIHdpbGwgdXNlIGEgdmVyeSBwb3B1bGFyIG1ldGhvZCBjYWxsZWQgZWl0aGVyIFtrLWZvbGQgb3Igdi1mb2xkIGNyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vay1mb2xkLWNyb3NzLXZhbGlkYXRpb24vKXt0YXJnZXQ9Il9ibGFuayJ9LiAKClRoaXMgbWV0aG9kIGludm9sdmVzIGVzc2VudGlhbGx5IHByZWZvcm1pbmcgdGhlIGhvbGQgb3V0IG1ldGhvZCBpdGVyYXRpdmVseSB3aXRoIHRoZSB0cmFpbmluZyBkYXRhLiAKCkZpcnN0IHRoZSB0cmFpbmluZyBzZXQgaXMgZGl2aWRlZCBpbnRvIGsgb3IgdiBlcXVhbGx5IHNpemVkIHNtYWxsZXIgcGllY2VzLiAKClRoZW4gdGhlIG1vZGVsIGlzIHRyYWluZWQgb24gdGhlIG1vZGVsIG9uIGstMSBvciB2LTEgc3Vic2V0cyBvZiB0aGUgZGF0YSBpdGVyYXRpdmVseSAocmVtb3ZpbmcgYSBkaWZmZXJlbnQgdiBvciBrIHVudGlsbCBhbGwgcG9zc2libGUgay0xIG9yIHYtMSBzZXRzIGhhdmUgYmVlbiBldmFsdWF0ZWQpIHRvIGdldCBhIHNlbnNlIG9mIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgbW9kZWwuIFRoaXMgaXMgcmVhbGx5IHVzZWZ1bCBmb3IgZmluZSB0dW5pbmcgc3BlY2lmaWMgYXNwZWN0cyBvZiB0aGUgbW9kZWwgaW4gYSBwcm9jZXNzIGNhbGxlZCBtb2RlbCB0dW5pbmcuCgoKSGVyZSBpcyBhIHZpc3VhbGl6YXRpb24gb2YgaG93IHRoZSBmb2xkcyBhcmUgY3JlYXRlZDoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidmZvbGQucG5nIikpCmBgYAoKCk5vdGU6IFBlb3BsZSB0eXBpY2FsbHkgaWdub3JlIHNwYXRpYWwgZGVwZW5kZW5jZSB3aXRoIGNyb3NzIHZhbGlkYXRpb24gb2YgYWlyIHBvbGx1dGlvbiBtb25pdG9yaW5nIGRhdGEgaW4gdGhlIGFpciBwb2xsdXRpb24gZmllbGQsIHNvIHdlIHdpbGwgZG8gdGhlIHNhbWUuICBIb3dldmVyLCBpdCBtaWdodCBtYWtlIHNlbnNlIHRvIGxlYXZlIG91dCBibG9ja3Mgb2YgbW9uaXRvcnMgcmF0aGVyIHRoYW4gIHJhbmRvbSBpbmRpdmlkdWFsIG1vbml0b3JzIHRvIGhlbHAgYWNjb3VudCBmb3Igc29tZSBzcGF0aWFsIGRlcGVuZGVuY2UuCgpUaGUgW2B2Zm9sZF9jdigpYF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL3JlZmVyZW5jZS92Zm9sZF9jdi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZ1bmN0aW9uIG9mIHRoZSBgcnNhbXBsZWAgcGFja2FnZSBjYW4gYmUgdXNlZCB0byBwYXJzZSB0aGUgdHJhaW5pbmcgZGF0YSBpbnRvIGZvbGRzIGZvciBrLWZvbGQvdi1mb2xkIGNyb3NzIHZhbGlkYXRpb24uCgpUaGUgYHZgIGFyZ3VtZW50IHNwZWNpZmllcyB0aGUgbnVtYmVyIG9mIGZvbGRzIHRvIGNyZWF0ZS4KVGhlIGByZXBlYXRzYCBhcmd1bWVudCBzcGVjaWZpZXMgaWYgYW55IHNhbXBsZXMgc2hvdWxkIGJlIHJlcGVhdGVkIGFjcm9zcyBmb2xkcyAtIGRlZnVhbHQgaXMgYEZBTFNFYApUaGUgYHN0cmF0YWAgYXJndW1lbnQgc3BlY2lmaWVzIGEgdmFyaWFibGUgdG8gc3RyYXRpZnkgc2FtcGxlcyBhY3Jvc3MgZm9sZHMgKGp1c3QgbGlrZSBpbiBgaW5pdGlhbF9zcGxpdCgpYCkuCgpBZ2FpbiBiZWNhdXNlIHRoZXNlIGFyZSBjcmVhdGVkIGF0IHJhbmRvbSwgd2UgbmVlZCB0byB1c2UgdGhlIGJhc2UgYHNldC5zZWVkKClgIGZ1bmN0aW9uIGluIG9yZGVyIHRvIG9idGFpbiB0aGUgc2FtZSByZXN1bHRzIGVhY2ggdGltZSB3ZSBrbml0IHRoaXMgZG9jdW1lbnQuCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKCnZmb2xkX3BtIDwtcnNhbXBsZTo6dmZvbGRfY3YoZGF0YSA9IHRyYWluX3BtLCB2ID0gMTAgKQoKdmZvbGRfcG0KCgp2Zm9sZF9wbSRzcGxpdHMkYDFgCnZmb2xkX3BtJHNwbGl0cyRgMmAKYGBgCgpPbmNlIHRoZSBmb2xkcyBhcmUgY3JlYXRlZCB0aGV5IGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHBlZm9ybWFuY2UgYnkgZml0dGluZyB0aGUgbW9kZWwgdG8gZWFjaCBvZiB0aGUgcmVzYW1wbGVzIHRoYXQgd2UgY3JlYXRlZDoKCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImNyb3NzX3ZhbGlkYXRpb24ucG5nIikpCmBgYAoKCldlIGNhbiBmaXQgdGhlIG1vZGVsIHRvIG91ciBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzIHVzaW5nIHRoZSBgZml0X3Jlc2FtcGxlcygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UsIGJ5IHNwZWNpZnlpbmcgb3VyIHdvcmtmbG93IG9iamVjdCBhbmQgdGhlIGNyb3NzIHZhbGlkYXRpb24gZm9sZCBvYmplY3Qgd2UganVzdCBjcmVhdGVkLiBTZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9yZWZlcmVuY2UvZml0X3Jlc2FtcGxlcy5odG1sKSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KCmBgYHtyfQpjb250cm9sIDwtIGNvbnRyb2xfcmVzYW1wbGVzKHNhdmVfcHJlZCA9IFRSVUUpCnJlc2FtcGxlX2ZpdCA8LXR1bmU6OmZpdF9yZXNhbXBsZXMoUE1fd2Zsb3csIHZmb2xkX3BtKQoKYGBgCgpXZSBjYW4gbm93IHRha2UgYSBsb29rIGF0IHZhcmlvdXMgbWV0cmljcyBvZiBwZXJmb3JtYW5jZSBiYXNlZCBvbiB0aGUgZml0IG9mIG91ciAxMCBjcm9zcyB2YWxpZGF0aW9uICJyZXNhbXBsZXMiLiBUbyBkbyB0aGlzIHdlIHdpbGwgdXNlIHRoZSBgc2hvd19iZXN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4KCmBgYHtyfQp0dW5lOjpzaG93X2Jlc3QocmVzYW1wbGVfZml0LCBtZXRyaWMgPSAicm1zZSIsICJyc3EiKQpgYGAKCiMjIyBUdW5pbmcKCk5vdyBsZXQncyB0cnkgc29tZSB0dW5pbmcuCgpMZXQncyB0YWtlIGEgY2xvc2VyIGxvb2sgYXQgaG93IHRoZSBtb25pdG9yIHZhbHVlcyB2YXJ5IHdpdGggbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS4KCmBgYHtyfQoKdHJhaW5fcG0gJT4lIAogIGRwbHlyOjpzZWxlY3QodmFsdWUsIGxvbiwgbGF0KSAlPiUgCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gYyhsb24sIGxhdCksIAogICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicHJlZGljdG9yIiwgdmFsdWVzX3RvID0gImxvY192YWx1ZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsb2NfdmFsdWUsIHZhbHVlKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpICsgCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSkgKyAKICAjc2NhbGVfeV9sb2cxMCgpICsKICBmYWNldF93cmFwKH4gcHJlZGljdG9yLCBzY2FsZXMgPSAiZnJlZV94IikKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGEgc2luZ2xlIGxpbmVhciByZWxhdGlvbnNoaXAgZm9yIGVpdGhlciBvZiB0aGVzZSBwcmVkaWN0b3JzLiBUaHVzIHdlIG1pZ2h0IHdhbnQgdG8gdGhpbmsgYWJvdXQgdXNpbmcgIFtzcGxpbmVzXShodHRwczovL3d3dy5tYXRoLnVoLmVkdS9+amluZ3FpdS9tYXRoNDM2NC9zcGxpbmUucGRmKSBvciB0aGlzKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9udW1lcmljYWwtaW50ZXJwb2xhdGlvbi1uYXR1cmFsLWN1YmljLXNwbGluZS01MmMxMTU3Yjk4YWMpIG9yIGp1c3QgdGhpcyhodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3R1bmUvYXJ0aWNsZXMvZ2V0dGluZ19zdGFydGVkLmh0bWwpIG9yIHRoaXMoaHR0cHM6Ly93d3cucHN5Y2gubWNnaWxsLmNhL21pc2MvZmRhL2V4LWJhc2lzLWIxLmh0bWwpIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgaW4gb3VyIHRyYWluaW5nIGRhdGEgbW9yZSBjbG9zZWx5LiBGb3IgZXhhbXBsZSBmb3IgdGhlIGxhdGl0dWRlIHBsb3QgKGxlZnQpIGlmIHdlIGhhZCAyIGxpbmVzIGFuZCBvbmUgYnJlYWtwb2ludCBjYWxsZWQgYSBrbm90IGFyb3VuZCA0MCwgd2l0aCB0aGUgZmlyc3QgbGluZSBoYXZpbmcgYSBwb3NpdGl2ZSBzbG9wZSBhbmQgdGhlIHNlY29uZCB3aXRoIGEgbmVnYXRpdmUgc2xvcGUgdGhpcyB3b3VsZCBmaXQgdGhlIGRhdGEgbW9yZSBzaW1pbGFybHkgdG8gdGhlIGJsdWUgbGluZSBzaG93biBpbiB0aGUgZmlndXJlLgoKV2UgY2FuIHR1bmUgZm9yIHRoZSBudW1iZXIgb2Yga25vdHMgYnkgdXNpbmcgYSBzdGVwIGZ1bmN0aW9uIGluIHRoZSBgcmVjaXBlc2AgcGFja2FnZSBjYWxsZWQgYHN0ZXBfbnMoKWAgd2hlcmUgbnMgc3RhbmRzIGZvciBuYXR1cmFsIHNwbGluZXMuIEluIG9yZGVyIHRvIHR1bmUgZm9yIHRoZSBudW1iZXIgb2Yga25vdHMgb3IgZGVncmVlcyBvZiBmcmVlZG9tLCB3ZSBjYW4gc2V0IHRoZSBgZGVnX2ZyZWVgIGFyZ3VtZW50IHRvIGB0dW5lKClgLiBUaGlzIGlzIGhlbHBmdWwsIGJlY3Vhc2Ugd2UgYXJlbid0IGV4YWN0bHkgc3VyZSBob3cgY2xvc2VseSB3ZSBzaG91bGQgYmUgZm9sbG93aW5nIHRoZSByZWxhdGlvbnNoaXAgd2l0aCB0aGUgdmFsdWUgYW5kIG91ciBsb25naXR1ZGUgYW5kIGxhdGl0dWRlIGRhdGEgaW4gb3VyIHRyYWluaW5nIGRhdGEgdG8gYWNoaWV2ZSBnb29kIGFjY3VyYWN5IHlldCBrZWVwIG91ciBtb2RlbCBnZW5lcmFsaXphYmxlIGZvciBvdGhlciBkYXRhLiAKClRoaXMgaXMgd2hlbiBvdXIgY3Jvc3MgdmFsaWRhdGlvbiBtZXRob2RzIGJlY29tZSByZWFsbHkgaGFuZHkuIFdlIGNhbiB0ZXN0IG91dCBkaWZmZXJlbnQgdmFsdWVzIGZvciB0aGUgYGRlZ19mcmVlYCBhcmd1bWVudCBhbmQgc2VlIGhvdyBvdXIgbW9kZWwgcGVyZm9ybWFuY2UgdmFyaWVzIGFjcm9zcyBvdXIgdHJhaW5pbmcgZm9sZHMgdG8gdHJ5IHRvIGZpbmQgdGhlIG9wdGltYWwgdmFsdWUuCgpXZSB3aWxsIHVwZGF0ZSBvdXIgcmVjaXBlIHRvIGFkZCB0aGVzZSBzdGVwcy4gSXQgaXMgYSBnb29kIGlkZWEgdG8gZG8gdGhpcyBmb3IgaW5kaXZpZHVhbCBwcmVkaWN0b3JzIGJlY2F1c2UgeW91IGNhbiBuYW1lIGVhY2ggd2l0aCB0aGUgYHR1bmVgIGFyZ3VtZW50IHNvIHRoYXQgeW91IGNhbiBrZWVwIHRyYWNrIG9mIGl0IGxhdGVyLiBXZSBjYW4gc2VlIHdoYXQgd2UgaW50ZW5kIHRvIHR1bmUgd2l0aCB0aGUgYHBhcmFtZXRlcnMoKWAgZnVuY3Rpb24gb2YgdGhlIGBkaWFsc2AgcGFja2FnZS4gCgpTZWUgW2hlcmVdKHRoaXMoaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby90dW5lL2FydGljbGVzL2dldHRpbmdfc3RhcnRlZC5odG1sKSkgZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaW1wbGVtZW50aW5nIHRoaXMgaW4gdGlkeW1vZGVscy4KCmBgYHtyfQoKc2ltcGxlX3JlYyAlPD4lCiAgc3RlcF9ucyhsb24sIGRlZ19mcmVlID0gdHVuZSgibG9uIGRmIikpICU+JQogIHN0ZXBfbnMobGF0LCAgZGVnX2ZyZWUgPSB0dW5lKCJsYXQgZGYiKSkKIyBzaW1wbGVfcmVjICU8PiUKIyAgIHN0ZXBfbnMobGF0LCAgZGVnX2ZyZWUgPSB0dW5lKCkpCiMgc2ltcGxlX3JlYwoKcG1fcGFyYW0gPC1kaWFsczo6cGFyYW1ldGVycyhzaW1wbGVfcmVjKQpwbV9wYXJhbQpgYGAKR2VuZWFybGx5IHlvdSBjb3VsZCB1c2UgdGhlIGBncmlkXyooKWAgZnVuY3Rpb25zIG9mIHRoZSBgZGlhbHNgIHBhY2thZ2UgdG8gY3JlYXRlIHRoZSBkaWZmZXJlbnQgY29tYmluYXRpb25zIG9mIGRlZ3JlZXMgb2YgZnJlZWRvbSB0byB0ZXN0IGZvciBib3RoIHZhcmlhYmxlcyB0byBvcHRpbWl6ZSB0aGUgbW9kZWwuIEluIG91ciBjYXNlIHdlIGNhbiB2aXNhYmx5IHNlZSB0aGF0IGlmIHdlIGFkZCBtb3JlIHRoYW4gc2F5IDQgb3IgNSBkZWdyZWVzIG9mIGZyZWVkb20gd2Ugd2lsbCBsaWtlbHkgb3ZlcmZpdCB0aGUgZGF0YS4gU28gaW5zdGVhZCBvZiB1c2luZyB0aGVzZSBmdW5jdGlvbnMgd2Ugd2lsbCBjcmVhdGUgb3VyIG93biBncmlkIHVzaW5nIHRoZSBiYXNlIGBzZXEoKWAgYW5kIGBleHBhbmQuZ3JpZCgpYCBmdW5jdGlvbnMuCgpgYGB7cn0KI2FuIGV4YW1wbGUgb2Ygd2hhdCB5b3UgY291bGQgZG86CiNzcGxpbmVfZ3JpZCA8LWRpYWxzOjpncmlkX3JlZ3VsYXIocG1fcGFyYW0sIGxldmVscyA9IDMpCmRmX3ZhbHMgPC0gc2VxKDEsIDUsIGJ5ID0gMikKc3BsaW5lX2dyaWQgPC0gZXhwYW5kLmdyaWQoYGxvbiBkZmAgPSBkZl92YWxzLCBgbGF0IGRmYCA9IGRmX3ZhbHMpCnNwbGluZV9ncmlkCmBgYAoKCk5vdyB3ZSB3aWxsIHR1bmUgdGhpcyBoeXBlci1wYXJhbWV0ZXIgKGRlZ3JlZXMgb2YgZnJlZWRvbSkgZm9yIGJvdGggdGhlIGBsYXRgIGFuZCBgbG9uYCB2YXJpYWJsZXMgdXNpbmcgb3VyIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMuIFRvIGRvIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLgoKYGBge3J9CgpkZl90dW5pbmcgPC1sbV9QTV9tb2RlbCAlPiUgCiAgdHVuZTo6dHVuZV9ncmlkKHNpbXBsZV9yZWMsIHJlc2FtcGxlcyA9dmZvbGRfcG0sIAogICAgICAgICAgICAgICAgICBncmlkID0gc3BsaW5lX2dyaWQpCgojZGZfdHVuaW5nIDwtUE1fd2Zsb3cgJT4lIHR1bmU6OnR1bmVfZ3JpZChyZXNhbXBsZXMgPXZmb2xkX3BtLCAKICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZCA9IHNwbGluZV9ncmlkLCAKICAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtX3NldCA9cG1fcGFyYW0pCgpkZl90dW5pbmcKYGBgCgoKCmBgYHtyfQoKZGZfdHVuaW5nICU+JQogIGNvbGxlY3RfbWV0cmljcygpCgpjb2xsZWN0X21ldHJpY3MoZGZfdHVuaW5nKQpzaG93X2Jlc3QoZGZfdHVuaW5nLCBtZXRyaWMgPSAicm1zZSIsIG4gPTEpCmBgYAoKCkxldCdzIHJldmlldyBldmVyeXRoaW5nOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0aWR5bW9kZWxzX2Vjb3N5c3RlbS5wbmciKSkKYGBgCgoKCgo+IGNoZWNrX25ld192YWx1ZXM6IFRoaXMgY2hlY2sgd2lsbCBicmVhayB0aGUgYmFrZSBmdW5jdGlvbiBpZiBhbnkgb2YgdGhlIGNoZWNrZWQgY29sdW1ucyBkb2VzIGNvbnRhaW4gdmFsdWVzIGl0IGRpZApub3QgY29udGFpbiB3aGVuIHByZXAgd2FzIGNhbGxlZCBvbiB0aGUgcmVjaXBlLiBJZiB0aGUgY2hlY2sgcGFzc2VzLCBub3RoaW5nIGlzIGNoYW5nZWQgdG8gdGhlIGRhdGEKCj4gY2hlY2tfcmFuZ2UgY3JlYXRlcyBhIHNwZWNpZmljYXRpb24gb2YgYSByZWNpcGUgY2hlY2sgdGhhdCB3aWxsIGNoZWNrIGlmIHRoZSByYW5nZSBvZiBhIG51bWVyaWMKdmFyaWFibGUgY2hhbmdlZCBpbiB0aGUgbmV3IGRhdGEuCgoKCltwYXJhbWV0ZXIgdnMgaHlwZXJwYXJhbWV0ZXJdKGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb21tdW5pdHkvdHV0b3JpYWxzL3BhcmFtZXRlci1vcHRpbWl6YXRpb24tbWFjaGluZS1sZWFybmluZy1tb2RlbHMpe3RhcmdldD0iX2JsYW5rIn0KCgoKcHJlcHBlciBmb3IgY3Jvc3MgdmFsaWRhdGlvbj8KCgoKCgoKZ3JlYXQgYmxvZyBhYm91dCBjcm9zcyB2YWxpZGF0aW9uIGV0YyBodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdGVzdC1zcGxpdC1hbmQtY3Jvc3MtdmFsaWRhdGlvbi1pbi1weXRob24tODBiNjFiZWNhNGI2CgojIyBEYXRhIFZpc3VhbGl6YXRpb24KCiMjIFN1bW1hcnkKCldlIGhhdmUgZXZhbHVhdGVkIGF2ZXJhZ2UgY29uc3VtcHRpb24gZXN0aW1hdGVzIG9mIDE1IGRpZXRhcnkgZmFjdG9ycyB3aXRoIHByb2JhYmx5IG5vbi1jb21tdW5pY2FibGUgZGlzZWFzZSAoTkNEKSByaXNrIGZyb20gMTk1IGRpZmZlcmVudCBjb3VudHJpZXMgYXJvdW5kIHRoZSB3b3JsZC4gVG8gZG8gc28gd2UgaW1wb3J0ZWQgZGF0YSBmcm9tIGEgUERGIHVzaW5nIHRoZSBgcGRmdG9vbHNgIHBhY2thZ2UsIGFzIHdlbGwgYXMgZGF0YSBmcm9tIHR3byBDU1YgZmlsZXMgdXNpbmcgcmVhZHIuIFdlIHVzZWQgYHRpZHl2ZXJzZWAgcGFja2FnZXMgc3VjaCBhcyBgZHBseXJgLCBgc3RyaW5ncmAsIGFuZCBgdGlkeWAgdG8gY2xlYW4gYW5kIGpvaW4gdGhlIGRhdGEgZnJvbSB0aGUgUERGIHdpdGggdGhlIENTViBmaWxlcy4gCgpXZSBsZWFybmVkIHRoYXQgUmVncmVzc2lvbiBpcyBhIHBvd2VyZnVsIGFuZCBmbGV4aWJsZSBzdGF0aXN0aWNhbCB0b29sIHRoYXQgc2ltcGxpZmllcyBvciBlc3RpbWF0ZXMgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMgdXNpbmcgYSBtYXRoZW1hdGljYWwgbW9kZWwuIFdlIGxlYXJuZWQgYWJvdXQgdGhlIHV0aWxpdHkgb2YgdGhlIHJlZ3Jlc3Npb24gdG8gY29tcGFyZSBncm91cHMsIGxvb2sgZm9yIGFzc29jaWF0aW9ucyBiZXR3ZWVuIHZhcmlhYmxlcywgYW5kIHRvIHByZWRpY3Qgb3V0Y29tZXMgYmFzZWQgb24gbXVsdGlwbGUgcHJlZGljdG9yIG9yIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4gV2UgdGhlbiBjb21wYXJlZCB0aGlzIHRvIG90aGVyIHBvcHVsYXIgdGVzdHMgbGlrZSB0aGUgJHQkLXRlc3QgYW5kIHRoZSBBTk9WQS4gV2UgbGVhcm5lZCB0aGF0IHRoZXNlIHRlc3RzIGFyZSBhY3R1YWxseSBlcXVpdmFsZW50IHRvIHNwZWNpYWxpemVkIHR5cGVzIG9mIHJlZ3Jlc3Npb25zLgoKT3VyIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGZvY3VzZWQgb24gZXZhbHVhdGluZyBkaWZmZXJlbmNlcyBpbiB0aGUgY29uc3VtcHRpb24gb2YgcmVkIG1lYXQgYXJvdW5kIHRoZSB3b3JsZCBiZXR3ZWVuIGZlbWFsZXMgYW5kIG1hbGVzIGFuZCBhY3Jvc3MgZGlmZmVyZW50IGFnZSBncm91cHMuIEZpcnN0IHdlIGxvb2tlZCBhdCB0aGUgYXNzdW1wdGlvbnMgb2YgWyR0JC10ZXN0c10oaHR0cHM6Ly9zdGF0dHJlay5jb20vc3RhdGlzdGljcy9kaWN0aW9uYXJ5LmFzcHg/ZGVmaW5pdGlvbj10d28tc2FtcGxlJTIwJHQkLXRlc3Qpe3RhcmdldD0iX2JsYW5rIn0gYW5kIHJlZ3Jlc3Npb25zLCBhbmQgZGV0ZXJtaW5lZCB0aGF0IHRoZSByZWxhdGl2ZSBwZXJjZW50YWdlIGRhdGEgb2YgcmVkIG1lYXQgY29uc3VtcHRpb24gdG8gdGhlIG9wdGltYWwgZ3VpZGVsaW5lIHN1Z2dlc3RlZCBhbW91bnQgd2FzIHJpZ2h0IHNrZXdlZC4gV2UgbGVhcm5lZCB0aGF0IHdlIGNvdWxkIHRyYW5zZm9ybSB0aGUgZGF0YSBieSB0YWtpbmcgdGhlIGxvZyBvZiB0aGVzZSB2YWx1ZXMgdG8gYWNoaWV2ZSBtb3JlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGRhdGEuIFRvIGNvbXBhcmUgbWFsZXMgYW5kIGZlbWFsZXMgd2UgdXNlZCBhICR0JC10ZXN0IGFuZCBsZWFybmVkIHRoYXQgYSAkdCQtdGVzdCBpcyBhIHNwZWNpYWxpemVkIGZvcm0gb2YgYSBsaW5lYXIgcmVncmVzc2lvbi4gVG8gY29tcGFyZSB0aGUgMTUgZGlmZmVyZW50IGFnZSBncm91cHMgd2UgdXNlZCBhbiBBTk9WQSBhbmQgbGVhcm5lZCB0aGF0IHRoZSBBTk9WQSBpcyBhbHNvIGEgc3BlY2lhbGl6ZWQgZm9ybSBvZiBsaW5lYXIgcmVncmVzc2lvbi4gV2UgZXhhbWluZWQgaG93IHdlIG9idGFpbmVkIHRoZSBzYW1lIHJlc3VsdHMgdXNpbmcgZWl0aGVyIHN0YXRpc3RpY2FsIHRlc3QuIFRoaXMgd2FzIGFsc28gdGhlIGNhc2UgaWYgd2UgbG9va2VkIGF0IHRoZSBlZmZlY3Qgb2YgZ2VuZGVyIGFuZCBjb250cm9sbGVkIGZvciB0aGUgcGFpcmVkIGNvdW50cnkgc3RydWN0dXJlIGluIHRoZSBkYXRhIGJ5IGVpdGhlciBpbmNsdWRpbmcgYGxvY2F0aW9uX25hbWVgIGluIHRoZSBtb2RlbCBhcyBhbm90aGVyIHRlcm0gb3IgYnkgdXNpbmcgYSBtaXhlZCBlZmZlY3RzIG1vZGVsIHRvIGNvbnRyb2wgZm9yIHRoaXMgc3RydWN0dXJlIGFzIGEgcmFuZG9tIGVmZmVjdCBidXQgbm90IHNwZWNpZmljYWxseSB0ZXN0IGZvciB0aGUgaW5mbHVlbmNlIG9mIGBsb2NhdGlvbl9uYW1lYCBvbiByZWQgbWVhdCBjb25zdW1wdGlvbiBlc3RpbWF0ZXMuIFdlIGxlYXJuZWQgdGhhdCBmaXhlZCBlZmZlY3RzIGFyZSB0aG9zZSB0aGF0IHdlIHdpc2ggdG8gZXZhbHVhdGUsIHdoaWxlIHJhbmRvbSBlZmZlY3RzIGFyZSB0aG9zZSB0aGF0IG1heSBpbmZsdWVuY2UgdGhlIHJlbGF0aW9uc2hpcHMgb2Ygb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCBidXQgdGhhdCB3ZSBkbyBub3Qgd2lzaCB0byBhY3RpdmVseSBldmFsdWF0ZS4gVXNpbmcgdGhlc2UgdGVzdHMgYW5kIG1vZGVscywgd2UgZGV0ZXJtaW5lZCB0aGF0IG1hbGVzIGNvbnN1bWUgbW9yZSByZWQgbWVhdCB0aGFuIHdvbWVuIG9uIGF2ZXJhZ2UgYXJvdW5kIHRoZSB3b3JsZC4gCgpPdXIgQU5PVkEgYW5hbHlzaXMgb2YgYWdlIGRldGVybWluZWQgdGhhdCBpbmRlZWQgdGhlcmUgYXQgbGVhc3Qgb25lIGFnZSBncm91cCBjb25zdW1lZCBhIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGFtb3VudCBvZiByZWQgbWVhdCBjb21wYXJlZCB0byB0aGUgb3RoZXIgYWdlIGdyb3VwcywgYW5kIHRoaXMgd2FzIHN0aWxsIHRoZSBjYXNlIHdoZW4gd2UgY29udHJvbGxlZCBgbG9jYXRpb25fbmFtZWAuIEhvd2V2ZXIsIHdlIGxlYXJuZWQgdGhhdCB3ZSBjb3VsZCB0aGF0IHRoZSBBTk9WQSBkb2VzIG5vdCBwcm92aWRlIGluZm9ybWF0aW9uIGFib3V0IHdoaWNoIGFnZSBncm91cHMgYXJlIGRpZmZlcmVudC4gV2UgbGVhcm5lZCBob3cgdGhlIHJlZ3Jlc3Npb24gaG93ZXZlciBjb3VsZCBwcm92aWRlIHNvbWUgY29tcGFyaXNvbnMgb2YgZGlmZmVyZW50IGFnZSBncm91cHMgcmVsYXRpdmUgdG8gdGhlIHJlZmVyZW5jZSBhZ2UgZ3JvdXAuIEZ1cnRoZXJtb3JlLCBvdXIgZGF0YSB2aXN1YWxpemF0aW9ucyBhbGxvd2VkIHVzIHRvIGRldGVybWluZSB0aGF0IGluIGdlbmVyYWwgcmVkIG1ldCBjb25zdW1wdGlvbiBhcHBlYXJzIHRvIGJlIGhpZ2hlciBpbiB0aGUgeW91bmdlciBhZ2UgZ3JvdXBzIHJlbGF0aXZlIHRvIHRoZSBvbGRlciBhZ2UgZ3JvdXBzLiAKCkZpbmFsbHksIHdlIGFsc28gbG9va2VkIGF0IGRpZmZlcmVuY2VzIGluIHJlZCBtZWF0IGNvbnN1bXB0aW9uIGJldHdlZW4gdGhlIGRpZmZlcmVudCBjb3VudHJpZXMgYW5kIHNhdyBpbiBvdXIgQU5PVkEgYW5hbHlzaXMgYW5kIG91ciByZWdyZXNzaW9uIGFuYWx5c2lzIHRoYXQgdGhlcmUgd2VyZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcy4gV2Ugd2VyZSBhYmxlIHRvIHVzZSBhIHJlZ3Jlc3Npb24gdGhhdCBpbmNsdWRlZCBgc2V4YCwgYGFnZV9ncm91cF9uYW1lYCwgYW5kIGBsb2NhdGlvbl9uYW1lYCB0byBldmFsdWF0ZSB0aGUgaW5mbHVlbmNlIG9mIGVhY2ggb2YgdGhlIHRocmVlIGRlbW9ncmFwaGljIGZhY3RvcnMgb24gY29uc3VtcHRpb24gd2hpbGUgY29udHJvbGxpbmcgb3IgYWNjb3VudGluZyBmb3IgdGhlIG90aGVyIHR3by4gT3VyIHJlc3VsdHMgZGVtb25zdHJhdGVkIHRoYXQgYWxsIHRocmVlIGluZmx1ZW5jZWQgb3Igd2VyZSBhc3NvY2lhdGVkIHdpdGggcmVkIG1lYXQgY29uc3VtcHRpb24uCgpJbiBwcmVmb3JtaW5nIG91ciBzdGF0aXN0aWNhbCBhbmFseXNlcyB3ZSBsZWFybmVkIGFib3V0IHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgJHQkLXRlc3QsIHRoZSByZWdyZXNzaW9uLCBhbmQgdGhlIEFOT1ZBLiBXZSBhbHNvIGxlYXJuZWQgYWJvdXQgaW1wb3J0YW50IG1ldGhvZHMgdG8gdGVzdHMgdGhlc2UgYXNzdW1wdGlvbnMuCgojIyMjICR0JC10ZXN0IGFzc3VtcHRpb25zOgoKMSkgTm9ybWFsaXR5IG9mIHRoZSBkYXRhIGZvciBib3RoIGdyb3VwcyAodGhpcyBpcyBub3QgYXMgbXVjaCBvZiBhbiBpc3N1ZSBpZiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpcyByZWxhdGl2ZWx5IGxhcmdlIHRvdGFsIG4+MzAgLSBjYW4gZXZhbHVhdGUgYnkgcGxvdHRpbmcgdGhlIGRpc3RyaWJ1dGlvbiBhbmQgYnkgY3JlYXRpbmcgW1EtUSBwbG90c10oW1EtUSBQbG90c10oaHR0cDovL29ubGluZXN0YXRib29rLmNvbS8yL2FkdmFuY2VkX2dyYXBocy9xLXFfcGxvdHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSkpCjIpIEVxdWFsIHZhcmlhbmNlIGJldHdlZW4gdGhlIHR3byBncm91cHMgKG1ha2Ugc3VyZSB5b3UgZG8gdGhlIGNvcnJlY3QgdGVzdCBpZiB0aGUgZGF0YSBpcyBub3Qgbm9ybWFsKQozKSBCYWxhbmNlZCBzYW1wbGUgc2l6ZXMgb2YgdGhlIHR3byBncm91cHMKNCkgSW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zIChvciBpbmRlcGVuZGVudCBwYWlyZWQgb2JzZXJ2YXRpb25zKQoKV2UgY2FuIGV2YWx1YXRlIGlmIG91ciBkYXRhIGlzIFtub3JtYWxseSBkaXN0cmlidXRlZF0oaHR0cHM6Ly93d3cucGh5c2lvbG9neS5vcmcvZG9pL2Z1bGwvMTAuMTE1Mi9hZHZhbi4wMDA2NC4yMDE3KXt0YXJnZXQ9Il9ibGFuayJ9IGJ5IHBsb3R0aW5nIHRoZSBkaXN0cmlidXRpb24gYW5kIGJ5IGNyZWF0aW5nIFtRLVEgcGxvdHNdKFtRLVEgUGxvdHNdKGh0dHA6Ly9vbmxpbmVzdGF0Ym9vay5jb20vMi9hZHZhbmNlZF9ncmFwaHMvcS1xX3Bsb3RzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gdG8gY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIG91ciBkYXRhIHRvIHRoZSB0aGVvcmV0aWNhbCBbbm9ybWFsIGRpc3RyaWJ1dGlvbl0oaHR0cHM6Ly93d3cucGh5c2lvbG9neS5vcmcvZG9pL2Z1bGwvMTAuMTE1Mi9hZHZhbi4wMDA2NC4yMDE3KXt0YXJnZXQ9Il9ibGFuayJ9LgoKPHU+SWYgb3VyIGRhdGEgaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB3ZSBjYW4gY29uc2lkZXIgdGhlc2Ugb3B0aW9uczo8L3U+CgoxKSBXZSBjYW4gc3RpbGwgcGVyZm9ybSBhICR0JC10ZXN0IGlmIG91ciBuIGlzIGxhcmdlCjIpIFdlIGNhbiB0cmFuc2Zvcm0gdGhlIGRhdGEgYmVmb3JlIHBlcmZvcm1pbmcgYSAkdCQtdGVzdAozKSBXZSBjYW4gdXNlIGEgbm9ucGFyYW1ldHJpYyB0ZXN0IChXaWxjb3hvbiBzaWduZWQgcmFuayB0ZXN0LCB0aGUgV2lsY294b24gcmFuayBzdW0gdGVzdCwgYW5kIHRoZSBUd28tc2FtcGxlIEtvbG1vZ29yb3YtU21pcm5vdiAoS1MpIHRlc3QpCjQpIFdlIGNhbiBwZXJmb3JtIGEgJHQkLXRlc3Qgd2l0aCByZXNhbXBsaW5nIG1ldGhvZHMgKHdoaWNoIHNob3VsZCBiZSBlc3BlY2lhbGx5IGNvbnNpZGVyZWQgd2hlbiB0aGUgZ3JvdXBzIGFyZSBpbWJhbGFuY2VkKQoKU2VlIHRoaXMgW2Nhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYnAtcnVyYWwtYW5kLXVyYmFuLW9iZXNpdHkpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gJHQkLXRlc3QgYXNzdW1wdGlvbnMuCgpXZSBsZWFybmVkIHRoYXQgd2UgY2FuIHRlc3QgaWYgMiBncm91cHMgaGF2ZSBlcXVhbCB2YXJpYW5jZSB1c2luZzogIAoxKSB0aGUgRiB0ZXN0IHdpdGggYHZhci50ZXN0KClgICAKMikgTW9vZCdzIHRlc3QgdXNpbmcgW2Btb29kLnRlc3QoKWBdKGh0dHBzOi8vZmlsZXMuZXJpYy5lZC5nb3YvZnVsbHRleHQvRUQwNjU1NTkucGRmKSAodXNlIGlmIHRoZSBkYXRhIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCkgIAoKIyMjIyBMaW5lYXIgcmVncmVzc2lvbiBhc3N1bXB0aW9uczoKCkwgKGxpbmVhcikgLSBUaGVyZSBpcyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdmFyaWFibGVzLiAgCkkgKGluZGVwZW5kZW50KSAtIFRoZSBzYW1wbGVzIGFyZSBpbmRlcGVuZGVudCBmcm9tIG9uZSBhbm90aGVyLiAgCk4gKG5vcm1hbCkgLSBUaGUgcmVzaWR1YWxzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4gIApFIChlcXVhbCB2YXJpYW5jZXMpIC0gVGhlIHZhcmlhbmNlIG9mIHRoZSByZXNpZHVhbHMgb2YgdGhlIGdyb3VwcyBpcyBzaW1pbGFyLiAgIApJdCBpcyBhbHNvIGltcG9ydGFudCB0aGF0IHByZWRpY3RvciB2YXJpYWJsZXMgYXJlIG5vdCBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIuICAKCiMjIyMgQU5PVkEgYXNzdW1wdGlvbnM6CgoxKSBOb3JtYWxpdHkgb2YgdGhlIGRhdGEgZm9yIGFsbCB0ZXN0ZWQgZ3JvdXBzIChsZXNzIG9mIGFuIGlzc3VlIGlmIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGlzIHJlbGF0aXZlbHkgbGFyZ2UgdG90YWwgbj4zMCkgCjIpIEVxdWFsIHZhcmlhbmNlIGJldHdlZW4gdGhlIGdyb3VwcyAtIGFrYSBIb21vZ2VuZWl0eSBvZiB2YXJpYW5jZSAobWFrZSBzdXJlIHlvdSBkbyB0aGUgY29ycmVjdCB0ZXN0IGlmIHRoZSBkYXRhIGlzIG5vdCBub3JtYWwpIAozKSBCYWxhbmNlZCBzYW1wbGUgc2l6ZXMgb2YgdGhlIGdyb3VwcyAKNCkgSW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zIChvciBpbmRlcGVuZGVudCBwYWlyZWQgb2JzZXJ2YXRpb25zKSAKCldlIGxlYXJuZWQgYWJvdXQgdGhyZWUgdGVzdHMgZm9yIGV4YW1pbmluZyB0aGUgZXF1YWxpdHkgb2YgdmFyaWFuY2Ugb2YgMyBvciBtb3JlIGdyb3VwczoKMSkgW0JhcnRsZXR0J3MgdGVzdF0oaHR0cHM6Ly93d3cuaXRsLm5pc3QuZ292L2Rpdjg5OC9oYW5kYm9vay9lZGEvc2VjdGlvbjMvZWRhMzU3Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSAod29ya3Mgd2VsbCBpZiB0aGUgZGF0YSBhcHBlYXJzIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkKSAKMikgW0ZsaWduZXItS2lsbGVlbl0oaHR0cDovL3dpa2kuc3RhdC51Y2xhLmVkdS9zb2NyL2luZGV4LnBocC9BUF9TdGF0aXN0aWNzX0N1cnJpY3VsdW1fMjAwN19Ob25QYXJhbV9WYXJJbmRlcCl7dGFyZ2V0PSJfYmxhbmsifSB0ZXN0IGlzIG5vbnBhcmFtZXRyaWMgYW5kIGRvZXMgbm90IGFzc3VtZSBub3JtYWxpdHkgCjMpIFtMZXZlbmUncyB0ZXN0XShodHRwczovL3d3dy5pdGwubmlzdC5nb3YvZGl2ODk4L2hhbmRib29rL2VkYS9zZWN0aW9uMy9lZGEzNWEuaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LCBpcyBtb3JlIHJvYnVzdCB0byB2aW9sYXRpb25zIG9mIG5vcm1hbGl0eSB0aGFuIHRoZSBCYXJ0bGV0dCdzIHRlc3QsIGJ1dCBub3QgYXMgcm9idXN0IGFzIHRoZSBGbGlnbmVyLSBLaWxsZWVuIHRlc3QgCgoKVXNpbmcgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHdlIHdlcmUgYWJsZSB0byB2aXN1YWxpemUgdHJlbmRzIGluIHRoZSBkYXRhIGFuZCB0byBjb21wYXJlIGNvbnN1bXB0aW9uIG9mIHRoZXNlIGRpZXRhcnkgZmFjdG9ycyBpbiB0aGUgVVMgd2l0aCB0aGF0IG9mIHRoZSBvdGhlciBjb3VudHJpZXMuCldlIHNlZSB0aGF0IHRoZSBwb3B1bGF0aW9ucyBpbiBtYW55IGNvdW50cmllcyBhcmUgb3Zlci1jb25zdW1pbmcgZm9vZHMgdGhhdCBhcmUgYXNzb2NpYXRlZCB3aXRoIGhlYWx0aCByaXNrIHdoZW4gb3Zlci1jb25zdW1lZC4gSW4gcGFydGljdWxhciBwcm9jZXNzZWQgbWVhdCBhbmQgc3VnYXItc3dlZXRlbmVkIGJldmVyYWdlcyBhcHBlYXIgdG8gYmUgdGhlIG1vc3Qgb3ZlciBjb25zdW1lZC4gSW1wb3J0YW50bHkgYm90aCBvZiB0aGVzZSBhcHBlYXIgdG8gYmUgY29uc3VtZWQgYXQgaGlnaGVyIHF1YW50aXRpZXMgYnkgbWFsZXMgYW5kIHlvdW5nZXIgYWR1bHRzLiBQZW9wbGUgaW4gdGhlIFVTICBhcHBlYXIgdG8gY29uc3VtZSBsZXNzIHN1Z2FyLXN3ZWV0ZW5lZCBiZXZlcmFnZXMgdGhhbiBvdGhlciBjb3VudHJpZXMsIGhvd2V2ZXIsIHBlb3BsZSBhcmUgc3RpbGwgb3Zlci1jb25zdW1pbmcuIFByb2Nlc3NlZCBtZWF0IGhvd2V2ZXIgYXBwZWFycyB0byBiZSBlc3BlY2lhbGx5IGJhZCBpbiB0aGUgVVMuIEluIHRlcm1zIG9mIGZvb2QgdGhhdCBuZWVkIHRvIGJlIGNvbnN1bWVkIGluIGFkZXF1YXRlIGFtb3VudHMgdG8gb3ZlcmNvbWUgaGVhbHRoIHJpc2ssIG5lYXJseSBhbGwgY291bnRyaWVzIGZvciBhbGwgZmFjdG9ycyBhcmUgbm90IHJlYWNoaW5nIGd1aWRlbGluZSBsZXZlbHMuIEhvd2V2ZXIsIHRoZXJlIGFyZSBzb21lIGNvdW50cmllcyBjb25zdW1pbmcgbW9yZSB0aGFuIGFkZXF1YXRlIGFtb3VudHMgb2YgbGVndW1lcywgdmVnZXRhYmxlcywgZnJ1aXRzIGFuZCBmaWJlci4gUGVvcGxlIGluIHRoZSBVUyBhcHBlYXIgdG8gZWF0IG1vcmUgbWlsayBwcm9kdWN0cyBhbmQgY29uc3VtZSBtb3JlIG9tZWdhLTMgZmF0dHkgYWNpZCBhbmQgY2FsY2l1bSByaWNoIGZvb2RzIHRoYW4gb3RoZXIgY291bnRyaWVzLiBBbGwgY291bnRyaWVzIGluY2x1ZGluZyB0aGUgVVMgY29uc3VtZSB2ZXJ5IGxvdyBsZXZlbHMgb2YgcG9seXVuc2F0dXJhdGVkIGZhdHR5IGFjaWRzLiBUaGVzZSBbcG9seXVuc2F0dXJhdGVkIGZhdHR5IGFjaWRzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Qb2x5dW5zYXR1cmF0ZWRfZmF0KSBhcmUgYWJ1bmRhbnQgaW4gc2VlZHMsIG51dHMsIGF2b2NhZG9zLCBhcyB3ZWxsIGFzIGZpc2guIExpa2VseSB0aGUgbG93IGxldmVsIG9mIGNvbnN1bXB0aW9uIG9mIG51dHMgYW5kIHNlZWRzIGNvbnRyaWJ1dGVzIHRvIHRoZXNlIGxvdyBwb2x5dW5zYXR1cmF0ZWQgZmF0dHkgYWNpZCBlc3RpbWF0ZXMuIFRoZSBzdXBwbGVtZW50YXJ5IHRhYmxlIGluY2x1ZGVkIGluIHRoZSBhcnRpY2xlIHN1Z2dlc3RzIHRoYXQgcG9vciBjb25zdW1wdGlvbiBvZiBwb2x5dW5zYXR1cmF0ZWQgZmF0dHkgYWNpZHMgaXMgYXNzb2NpYXRlZCB3aXRoIGlzY2hlbWljIGhlYXJ0IGRpc2Vhc2UuIFRoZSBhcnRpY2xlIHRha2VzIHRoaXMgZGF0YSBmdXJ0aGVyIHRvIGV2YWx1YXRlIHRoZSBhc3NvY2lhdGlvbiBvZiBjb25zdW1wdGlvbiBsZXZlbHMgb2YgdGhlc2UgZm9vZHMgd2l0aCBtb3J0YWxpdHkuCgpBbmFseXNlcyBsaWtlIHRoZSBvbmUgaW4gb3VyIGNhc2Ugc3R1ZHkgYXJlIGltcG9ydGFudCBmb3IgZGVmaW5pbmcgd2hpY2ggZ3JvdXBzIGNvdWxkIGJlbmVmaXQgdGhlIG1vc3QgZnJvbSBpbnRlcnZlbnRpb25zLCBlZHVjYXRpb24sIGFuZCBwb2xpY3kgY2hhbmdlcyB3aGVuIGF0dGVtcHRpbmcgdG8gbWl0aWdhdGUgcHVibGljIGhlYWx0aCBjaGFsbGVuZ2VzLiBZb3UgY2FuIHNlZSBpbiB0aGUgW2FydGljbGVdKGh0dHBzOi8vd3d3LnRoZWxhbmNldC5jb20vYWN0aW9uL3Nob3dQZGY/cGlpPVMwMTQwLTY3MzYlMjgxOSUyOTMwMDQxLTgpe3RhcmdldD0iX2JsYW5rIn0gaG93ZXZlciB0aGF0IG1hbnkgYWRkaXRpb25hbCBjb25zaWRlcmF0aW9ucyB3b3VsZCBiZSBpbnZvbHZlZCB0byBwZXJmb3JtIGEgbW9yZSB0aG9yb3VnaCBhbmFseXNpcyB0byBhZGVxdWF0ZWx5IHVuZGVyc3RhbmQgdGhlIGRhdGEgZW5vdWdoIHRvIHJlY29tbWVuZCBwb2xpY3kgY2hhbmdlcy4KCgojIyMgU3VnZ2VzdGVkIEhvbWV3b3JrCgpTdHVkZW50cyBjYW4gZXZhbHVhdGUgY29uc3VtcHRpb24gZXN0aW1hdGVzIG9mIGFub3RoZXIgZGlldGFyeSBmYWN0b3IgYmVzaWRlcyByZWQgbWVhdC4KCiMjIyBIZWxwZnVsIExpbmtzCgpyZXZpZXcgb2YgW3RpZHltb2RlbHNdKGh0dHBzOi8vcnZpZXdzLnJzdHVkaW8uY29tLzIwMTkvMDYvMTkvYS1nZW50bGUtaW50cm8tdG8tdGlkeW1vZGVscy8pe3RhcmdldD0iX2JsYW5rIn0gCgpndWlkZSBmb3IgW3ByZXByb2Nlc3Npbmcgd2l0aCByZWNpcGVzXShodHRwOi8vd3d3LnJlYmVjY2FiYXJ0ZXIuY29tL2Jsb2cvMjAxOS0wNi0wNl9wcmVfcHJvY2Vzc2luZy8pCgpbZ3VpZGVdKGh0dHBzOi8vYnJpYXR0ZS5naXRodWIuaW8vZ2djb3JyLykgZm9yIHVzaW5nIEdHYWxseSB0byBjcmVhdGUgY29ycmVsYXRpb24gcGxvdHMKW2d1aWRlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8xMS9wYXJzbmlwLTAtMC0xLykgZm9yIHVzaW5nIHBhcnNuaXAgdG8gdHJ5IGRpZmZlcmVudCBhbGdvcml0aG1zIG9yIGVuZ2luZXMKW3JlY2lwZSBmdW5jdGlvbnNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCkKCjx1PlRlcm1zIGFuZCBjb25jZXB0cyBjb3ZlcmVkOjwvdT4gIAoKW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gIApbUlN0dWRpbyBjaGVhdHNoZWV0c10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0luZmVyZW5jZV0oaHR0cHM6Ly93d3cuYnJpdGFubmljYS5jb20vc2NpZW5jZS9pbmZlcmVuY2Utc3RhdGlzdGljcyl7dGFyZ2V0PSJfYmxhbmsifSAgCltSZWdyZXNzaW9uXShodHRwczovL2xpbmRlbG9ldi5naXRodWIuaW8vdGVzdHMtYXMtbGluZWFyLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltEaWZmZXJlbnQgdHlwZXMgb2YgcmVncmVzc2lvbl0oaHR0cHM6Ly93d3cuYW5hbHl0aWNzdmlkaHlhLmNvbS9ibG9nLzIwMTUvMDgvY29tcHJlaGVuc2l2ZS1ndWlkZS1yZWdyZXNzaW9uLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltPcmRpbmFyeSBsZWFzdCBzcXVhcmVzIG1ldGhvZF0oaHR0cDovL3NldG9zYS5pby9ldi9vcmRpbmFyeS1sZWFzdC1zcXVhcmVzLXJlZ3Jlc3Npb24vKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1Jlc2lkdWFsXShodHRwczovL3d3dy5zdGF0aXN0aWNzaG93dG8uZGF0YXNjaWVuY2VjZW50cmFsLmNvbS9yZXNpZHVhbC8pe3RhcmdldD0iX2JsYW5rIn0gIAoKPHU+UGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6IDwvdT4KCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEgIApbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YSAgCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gYXJyYW5nZS9maWx0ZXIvc2VsZWN0L2NvbXBhcmUgc3BlY2lmaWMgc3Vic2V0cyBvZiB0aGUgZGF0YSAgCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhICAgCltzdW1tYXJ5dG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YSBpbiBhIGRpZmZlcmVudCBzdHlsZSAgIApbcGRmdG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wZGZ0b29scy9wZGZ0b29scy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHJlYWQgYSBQREYgaW50byBSICAgClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgIApbcHVycnJdKGh0dHBzOi8vcHVycnIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHBlcmZvcm0gZnVuY3Rpb25zIG9uIGFsbCBjb2x1bW5zIG9mIGEgdGliYmxlICAgClt0aWJibGVdKGh0dHBzOi8vdGliYmxlLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICB8IHRvIGNyZWF0ZSBkYXRhIG9iamVjdHMgdGhhdCB3ZSBjYW4gbWFuaXB1bGF0ZSB3aXRoICBkcGx5ci9zdHJpbmdyL3RpZHlyL3B1cnJyICAKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMgCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYWtlIHZpc3VhbGl6YXRpb25zIHdpdGggbXVsdGlwbGUgbGF5ZXJzICAKCgpEbyBJIG5lZWQgdG8gdGFsayBhYm91dCBtYWNoaW5lIGxlYXJuaW5nIGluIGdlbmVyYWwgbW9yZS4uLiBjbGFzc2lmaWNhdGlvbiB2cyBwcmVkaWN0aW9uPw==